diff --git a/apps/mobile/patches/@react-native+community-cli-plugin+0.77.2.patch b/apps/mobile/patches/@react-native+community-cli-plugin+0.77.2.patch
new file mode 100644
index 000000000..32913b424
--- /dev/null
+++ b/apps/mobile/patches/@react-native+community-cli-plugin+0.77.2.patch
@@ -0,0 +1,11 @@
+diff --git a/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js b/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js
+index c0749e1..bbcb97e 100644
+--- a/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js
++++ b/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js
+@@ -83,5 +83,6 @@ This warning will be removed in future (https://github.com/facebook/metro/issues
+ ...options,
+ });
+ const overrideConfig = getOverrideConfig(ctx, config);
++ if (!overrideConfig.resolver.resolveRequest) delete overrideConfig.resolver.resolveRequest;
+ return (0, _metroConfig.mergeConfig)(config, overrideConfig);
+ }
diff --git a/apps/mobile/patches/react-native-mmkv-storage+0.11.2.patch b/apps/mobile/patches/react-native-mmkv-storage+0.11.2.patch
new file mode 100644
index 000000000..608edee0f
--- /dev/null
+++ b/apps/mobile/patches/react-native-mmkv-storage+0.11.2.patch
@@ -0,0 +1,9159 @@
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2
+new file mode 100644
+index 0000000..e69de29
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1
+new file mode 100644
+index 0000000..e69de29
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2
+new file mode 100644
+index 0000000..e69de29
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/cache-v2-4fcc3a0282421a2d3b89.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/cache-v2-4fcc3a0282421a2d3b89.json
+new file mode 100644
+index 0000000..37940c6
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/cache-v2-4fcc3a0282421a2d3b89.json
+@@ -0,0 +1,1615 @@
++{
++ "entries" :
++ [
++ {
++ "name" : "ANDROID_ABI",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "arm64-v8a"
++ },
++ {
++ "name" : "ANDROID_NDK",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006"
++ },
++ {
++ "name" : "ANDROID_PLATFORM",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "android-24"
++ },
++ {
++ "name" : "ANDROID_STL",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "c++_shared"
++ },
++ {
++ "name" : "CMAKE_ADDR2LINE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line"
++ },
++ {
++ "name" : "CMAKE_ANDROID_ARCH_ABI",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "arm64-v8a"
++ },
++ {
++ "name" : "CMAKE_ANDROID_NDK",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006"
++ },
++ {
++ "name" : "CMAKE_AR",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Archiver"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar"
++ },
++ {
++ "name" : "CMAKE_ASM_COMPILER",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "ASM compiler"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang"
++ },
++ {
++ "name" : "CMAKE_ASM_COMPILER_AR",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "LLVM archiver"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar"
++ },
++ {
++ "name" : "CMAKE_ASM_COMPILER_RANLIB",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Generate index for LLVM archive"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib"
++ },
++ {
++ "name" : "CMAKE_ASM_COMPILER_WORKS",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : ""
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "1"
++ },
++ {
++ "name" : "CMAKE_ASM_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during all build types."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_ASM_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during debug builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_ASM_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the ASM compiler during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-Os -DNDEBUG"
++ },
++ {
++ "name" : "CMAKE_ASM_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during release builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_ASM_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the ASM compiler during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-O2 -g -DNDEBUG"
++ },
++ {
++ "name" : "CMAKE_BUILD_TYPE",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "Debug"
++ },
++ {
++ "name" : "CMAKE_CACHEFILE_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "This is the directory where this CMakeCache.txt was created"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a"
++ },
++ {
++ "name" : "CMAKE_CACHE_MAJOR_VERSION",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Major version of cmake used to create the current loaded cache"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "3"
++ },
++ {
++ "name" : "CMAKE_CACHE_MINOR_VERSION",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Minor version of cmake used to create the current loaded cache"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "22"
++ },
++ {
++ "name" : "CMAKE_CACHE_PATCH_VERSION",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Patch version of cmake used to create the current loaded cache"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "1"
++ },
++ {
++ "name" : "CMAKE_COMMAND",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to CMake executable."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake"
++ },
++ {
++ "name" : "CMAKE_CPACK_COMMAND",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to cpack program executable."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cpack"
++ },
++ {
++ "name" : "CMAKE_CTEST_COMMAND",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to ctest program executable."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ctest"
++ },
++ {
++ "name" : "CMAKE_CXX_COMPILER",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "(This variable does not exist and should not be used)"
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_CXX_COMPILER_AR",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "LLVM archiver"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar"
++ },
++ {
++ "name" : "CMAKE_CXX_COMPILER_LAUNCHER",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Compiler launcher for CXX."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "ccache"
++ },
++ {
++ "name" : "CMAKE_CXX_COMPILER_RANLIB",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Generate index for LLVM archive"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib"
++ },
++ {
++ "name" : "CMAKE_CXX_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during all build types."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-O3 -frtti -fexceptions -Wall -fstack-protector-all"
++ },
++ {
++ "name" : "CMAKE_CXX_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during debug builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_CXX_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the CXX compiler during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-Os -DNDEBUG"
++ },
++ {
++ "name" : "CMAKE_CXX_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during release builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-O2 -g -DNDEBUG"
++ },
++ {
++ "name" : "CMAKE_CXX_STANDARD_LIBRARIES",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Libraries linked by default with all C++ applications."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-latomic -lm"
++ },
++ {
++ "name" : "CMAKE_C_COMPILER",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "(This variable does not exist and should not be used)"
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_C_COMPILER_AR",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "LLVM archiver"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar"
++ },
++ {
++ "name" : "CMAKE_C_COMPILER_LAUNCHER",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Compiler launcher for C."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "ccache"
++ },
++ {
++ "name" : "CMAKE_C_COMPILER_RANLIB",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Generate index for LLVM archive"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib"
++ },
++ {
++ "name" : "CMAKE_C_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during all build types."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_C_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during debug builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_C_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the C compiler during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-Os -DNDEBUG"
++ },
++ {
++ "name" : "CMAKE_C_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the compiler during release builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the C compiler during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-O2 -g -DNDEBUG"
++ },
++ {
++ "name" : "CMAKE_C_STANDARD_LIBRARIES",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Libraries linked by default with all C applications."
++ }
++ ],
++ "type" : "STRING",
++ "value" : "-latomic -lm"
++ },
++ {
++ "name" : "CMAKE_DLLTOOL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-dlltool"
++ },
++ {
++ "name" : "CMAKE_EDIT_COMMAND",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to cache edit program executable."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ccmake"
++ },
++ {
++ "name" : "CMAKE_EXECUTABLE_FORMAT",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Executable file format"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "ELF"
++ },
++ {
++ "name" : "CMAKE_EXE_LINKER_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during DEBUG builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during RELEASE builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_EXPORT_COMPILE_COMMANDS",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "ON"
++ },
++ {
++ "name" : "CMAKE_EXTRA_GENERATOR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Name of external makefile project generator."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_FIND_ROOT_PATH",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab"
++ },
++ {
++ "name" : "CMAKE_GENERATOR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Name of generator."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "Ninja"
++ },
++ {
++ "name" : "CMAKE_GENERATOR_INSTANCE",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Generator instance identifier."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_GENERATOR_PLATFORM",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Name of generator platform."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_GENERATOR_TOOLSET",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Name of generator toolset."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_HOME_DIRECTORY",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Source directory with the top level CMakeLists.txt file for this project"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv"
++ },
++ {
++ "name" : "CMAKE_INSTALL_PREFIX",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Install path prefix, prepended onto install directories."
++ }
++ ],
++ "type" : "PATH",
++ "value" : "/usr/local"
++ },
++ {
++ "name" : "CMAKE_INSTALL_SO_NO_EXE",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Install .so files without execute permission."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "0"
++ },
++ {
++ "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a"
++ },
++ {
++ "name" : "CMAKE_LINKER",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld"
++ },
++ {
++ "name" : "CMAKE_MAKE_PROGRAM",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja"
++ },
++ {
++ "name" : "CMAKE_MODULE_LINKER_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of modules."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of modules during DEBUG builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of modules during RELEASE builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_NM",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm"
++ },
++ {
++ "name" : "CMAKE_NUMBER_OF_MAKEFILES",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "number of local generators"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "2"
++ },
++ {
++ "name" : "CMAKE_OBJCOPY",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy"
++ },
++ {
++ "name" : "CMAKE_OBJDUMP",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump"
++ },
++ {
++ "name" : "CMAKE_PLATFORM_INFO_INITIALIZED",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Platform information initialized"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "1"
++ },
++ {
++ "name" : "CMAKE_PROJECT_DESCRIPTION",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_PROJECT_HOMEPAGE_URL",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_PROJECT_NAME",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "PACKAGE_NAME"
++ },
++ {
++ "name" : "CMAKE_RANLIB",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Ranlib"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib"
++ },
++ {
++ "name" : "CMAKE_READELF",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a program."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf"
++ },
++ {
++ "name" : "CMAKE_ROOT",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to CMake installation."
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22"
++ },
++ {
++ "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a"
++ },
++ {
++ "name" : "CMAKE_SHARED_LINKER_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of dll's."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_SKIP_INSTALL_RPATH",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building."
++ }
++ ],
++ "type" : "BOOL",
++ "value" : "NO"
++ },
++ {
++ "name" : "CMAKE_SKIP_RPATH",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "If set, runtime paths are not added when using shared libraries."
++ }
++ ],
++ "type" : "BOOL",
++ "value" : "NO"
++ },
++ {
++ "name" : "CMAKE_STATIC_LINKER_FLAGS",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of static libraries during all build types."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds."
++ }
++ ],
++ "type" : "STRING",
++ "value" : ""
++ },
++ {
++ "name" : "CMAKE_STRIP",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "Strip"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip"
++ },
++ {
++ "name" : "CMAKE_SYSTEM_NAME",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "Android"
++ },
++ {
++ "name" : "CMAKE_SYSTEM_VERSION",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "24"
++ },
++ {
++ "name" : "CMAKE_TOOLCHAIN_FILE",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "The CMake toolchain file"
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake"
++ },
++ {
++ "name" : "CMAKE_UNAME",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "uname command"
++ }
++ ],
++ "type" : "INTERNAL",
++ "value" : "/usr/bin/uname"
++ },
++ {
++ "name" : "CMAKE_VERBOSE_MAKEFILE",
++ "properties" :
++ [
++ {
++ "name" : "ADVANCED",
++ "value" : "1"
++ },
++ {
++ "name" : "HELPSTRING",
++ "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo."
++ }
++ ],
++ "type" : "BOOL",
++ "value" : "FALSE"
++ },
++ {
++ "name" : "PACKAGE_NAME_BINARY_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a"
++ },
++ {
++ "name" : "PACKAGE_NAME_IS_TOP_LEVEL",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "ON"
++ },
++ {
++ "name" : "PACKAGE_NAME_SOURCE_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv"
++ },
++ {
++ "name" : "REACT_NATIVE_MINOR_VERSION",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "No help, variable specified on the command line."
++ }
++ ],
++ "type" : "UNINITIALIZED",
++ "value" : "77"
++ },
++ {
++ "name" : "ReactAndroid_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "The directory containing a CMake configuration file for ReactAndroid."
++ }
++ ],
++ "type" : "PATH",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid"
++ },
++ {
++ "name" : "core_BINARY_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core"
++ },
++ {
++ "name" : "core_IS_TOP_LEVEL",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "OFF"
++ },
++ {
++ "name" : "core_LIB_DEPENDS",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Dependencies for the target"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "general;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so;"
++ },
++ {
++ "name" : "core_SOURCE_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Value Computed by CMake"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core"
++ },
++ {
++ "name" : "fbjni_DIR",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "The directory containing a CMake configuration file for fbjni."
++ }
++ ],
++ "type" : "PATH",
++ "value" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni"
++ },
++ {
++ "name" : "log-lib",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a library."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so"
++ },
++ {
++ "name" : "rnmmkv_LIB_DEPENDS",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Dependencies for the target"
++ }
++ ],
++ "type" : "STATIC",
++ "value" : "general;core;general;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so;general;fbjni::fbjni;general;ReactAndroid::jsi;general;ReactAndroid::reactnative;general;android;"
++ },
++ {
++ "name" : "zlib",
++ "properties" :
++ [
++ {
++ "name" : "HELPSTRING",
++ "value" : "Path to a library."
++ }
++ ],
++ "type" : "FILEPATH",
++ "value" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so"
++ }
++ ],
++ "kind" : "cache",
++ "version" :
++ {
++ "major" : 2,
++ "minor" : 0
++ }
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-1e19e9e1c2dd6b6409a0.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-1e19e9e1c2dd6b6409a0.json
+new file mode 100644
+index 0000000..1da75bf
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-1e19e9e1c2dd6b6409a0.json
+@@ -0,0 +1,892 @@
++{
++ "inputs" :
++ [
++ {
++ "path" : "CMakeLists.txt"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android-legacy.toolchain.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/abis.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/platforms.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Determine.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in"
++ },
++ {
++ "isGenerated" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Initialize.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Determine-Compiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in"
++ },
++ {
++ "isGenerated" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in"
++ },
++ {
++ "isGenerated" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Clang.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/flags.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in"
++ },
++ {
++ "isGenerated" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in"
++ },
++ {
++ "isGenerated" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfigVersion.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfig.cmake"
++ },
++ {
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineASMCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeASMCompiler.cmake.in"
++ },
++ {
++ "isGenerated" : true,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeASMCompiler.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeASMInformation.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-ASM.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-ASM.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake"
++ },
++ {
++ "isCMake" : true,
++ "isExternal" : true,
++ "path" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestASMCompiler.cmake"
++ }
++ ],
++ "kind" : "cmakeFiles",
++ "paths" :
++ {
++ "build" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "source" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv"
++ },
++ "version" :
++ {
++ "major" : 1,
++ "minor" : 0
++ }
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ef3ec3946d637dcb85cc.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ef3ec3946d637dcb85cc.json
+new file mode 100644
+index 0000000..ac4e8cb
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ef3ec3946d637dcb85cc.json
+@@ -0,0 +1,102 @@
++{
++ "configurations" :
++ [
++ {
++ "directories" :
++ [
++ {
++ "build" : ".",
++ "childIndexes" :
++ [
++ 1
++ ],
++ "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json",
++ "minimumCMakeVersion" :
++ {
++ "string" : "3.6.0"
++ },
++ "projectIndex" : 0,
++ "source" : ".",
++ "targetIndexes" :
++ [
++ 1
++ ]
++ },
++ {
++ "build" : "core",
++ "jsonFile" : "directory-core-Debug-0c55b56e6e49717d3843.json",
++ "minimumCMakeVersion" :
++ {
++ "string" : "3.10.0"
++ },
++ "parentIndex" : 0,
++ "projectIndex" : 1,
++ "source" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core",
++ "targetIndexes" :
++ [
++ 0
++ ]
++ }
++ ],
++ "name" : "Debug",
++ "projects" :
++ [
++ {
++ "childIndexes" :
++ [
++ 1
++ ],
++ "directoryIndexes" :
++ [
++ 0
++ ],
++ "name" : "PACKAGE_NAME",
++ "targetIndexes" :
++ [
++ 1
++ ]
++ },
++ {
++ "directoryIndexes" :
++ [
++ 1
++ ],
++ "name" : "core",
++ "parentIndex" : 0,
++ "targetIndexes" :
++ [
++ 0
++ ]
++ }
++ ],
++ "targets" :
++ [
++ {
++ "directoryIndex" : 1,
++ "id" : "core::@57760688d1f824db5d9c",
++ "jsonFile" : "target-core-Debug-6fdee91f06b602da4884.json",
++ "name" : "core",
++ "projectIndex" : 1
++ },
++ {
++ "directoryIndex" : 0,
++ "id" : "rnmmkv::@6890427a1f51a3e7e1df",
++ "jsonFile" : "target-rnmmkv-Debug-0134b721e8df58d1deb2.json",
++ "name" : "rnmmkv",
++ "projectIndex" : 0
++ }
++ ]
++ }
++ ],
++ "kind" : "codemodel",
++ "paths" :
++ {
++ "build" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "source" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv"
++ },
++ "version" :
++ {
++ "major" : 2,
++ "minor" : 3
++ }
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json
+new file mode 100644
+index 0000000..3a67af9
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json
+@@ -0,0 +1,14 @@
++{
++ "backtraceGraph" :
++ {
++ "commands" : [],
++ "files" : [],
++ "nodes" : []
++ },
++ "installers" : [],
++ "paths" :
++ {
++ "build" : ".",
++ "source" : "."
++ }
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/directory-core-Debug-0c55b56e6e49717d3843.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/directory-core-Debug-0c55b56e6e49717d3843.json
+new file mode 100644
+index 0000000..3aa9fe2
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/directory-core-Debug-0c55b56e6e49717d3843.json
+@@ -0,0 +1,14 @@
++{
++ "backtraceGraph" :
++ {
++ "commands" : [],
++ "files" : [],
++ "nodes" : []
++ },
++ "installers" : [],
++ "paths" :
++ {
++ "build" : "core",
++ "source" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core"
++ }
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/index-2025-05-21T04-48-09-0271.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/index-2025-05-21T04-48-09-0271.json
+new file mode 100644
+index 0000000..f7a9ea5
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/index-2025-05-21T04-48-09-0271.json
+@@ -0,0 +1,92 @@
++{
++ "cmake" :
++ {
++ "generator" :
++ {
++ "multiConfig" : false,
++ "name" : "Ninja"
++ },
++ "paths" :
++ {
++ "cmake" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake",
++ "cpack" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cpack",
++ "ctest" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ctest",
++ "root" : "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22"
++ },
++ "version" :
++ {
++ "isDirty" : false,
++ "major" : 3,
++ "minor" : 22,
++ "patch" : 1,
++ "string" : "3.22.1-g37088a8",
++ "suffix" : "g37088a8"
++ }
++ },
++ "objects" :
++ [
++ {
++ "jsonFile" : "codemodel-v2-ef3ec3946d637dcb85cc.json",
++ "kind" : "codemodel",
++ "version" :
++ {
++ "major" : 2,
++ "minor" : 3
++ }
++ },
++ {
++ "jsonFile" : "cache-v2-4fcc3a0282421a2d3b89.json",
++ "kind" : "cache",
++ "version" :
++ {
++ "major" : 2,
++ "minor" : 0
++ }
++ },
++ {
++ "jsonFile" : "cmakeFiles-v1-1e19e9e1c2dd6b6409a0.json",
++ "kind" : "cmakeFiles",
++ "version" :
++ {
++ "major" : 1,
++ "minor" : 0
++ }
++ }
++ ],
++ "reply" :
++ {
++ "client-agp" :
++ {
++ "cache-v2" :
++ {
++ "jsonFile" : "cache-v2-4fcc3a0282421a2d3b89.json",
++ "kind" : "cache",
++ "version" :
++ {
++ "major" : 2,
++ "minor" : 0
++ }
++ },
++ "cmakeFiles-v1" :
++ {
++ "jsonFile" : "cmakeFiles-v1-1e19e9e1c2dd6b6409a0.json",
++ "kind" : "cmakeFiles",
++ "version" :
++ {
++ "major" : 1,
++ "minor" : 0
++ }
++ },
++ "codemodel-v2" :
++ {
++ "jsonFile" : "codemodel-v2-ef3ec3946d637dcb85cc.json",
++ "kind" : "codemodel",
++ "version" :
++ {
++ "major" : 2,
++ "minor" : 3
++ }
++ }
++ }
++ }
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/target-core-Debug-6fdee91f06b602da4884.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/target-core-Debug-6fdee91f06b602da4884.json
+new file mode 100644
+index 0000000..bddfa4f
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/target-core-Debug-6fdee91f06b602da4884.json
+@@ -0,0 +1,589 @@
++{
++ "archive" : {},
++ "artifacts" :
++ [
++ {
++ "path" : "core/libcore.a"
++ }
++ ],
++ "backtrace" : 1,
++ "backtraceGraph" :
++ {
++ "commands" :
++ [
++ "add_library",
++ "target_include_directories",
++ "set_target_properties",
++ "target_sources"
++ ],
++ "files" :
++ [
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt"
++ ],
++ "nodes" :
++ [
++ {
++ "file" : 0
++ },
++ {
++ "command" : 0,
++ "file" : 0,
++ "line" : 72,
++ "parent" : 0
++ },
++ {
++ "command" : 1,
++ "file" : 0,
++ "line" : 149,
++ "parent" : 0
++ },
++ {
++ "command" : 2,
++ "file" : 0,
++ "line" : 157,
++ "parent" : 0
++ },
++ {
++ "command" : 3,
++ "file" : 0,
++ "line" : 144,
++ "parent" : 0
++ }
++ ]
++ },
++ "compileGroups" :
++ [
++ {
++ "compileCommandFragments" :
++ [
++ {
++ "fragment" : "-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC"
++ },
++ {
++ "fragment" : "-std=c++20"
++ }
++ ],
++ "includes" :
++ [
++ {
++ "backtrace" : 2,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core"
++ }
++ ],
++ "language" : "CXX",
++ "languageStandard" :
++ {
++ "backtraces" :
++ [
++ 3
++ ],
++ "standard" : "20"
++ },
++ "sourceIndexes" :
++ [
++ 1,
++ 2,
++ 4,
++ 5,
++ 7,
++ 8,
++ 10,
++ 11,
++ 13,
++ 14,
++ 16,
++ 18,
++ 20,
++ 22,
++ 23,
++ 25,
++ 27,
++ 28,
++ 29,
++ 31,
++ 32,
++ 33,
++ 34,
++ 35,
++ 37,
++ 38,
++ 41,
++ 43,
++ 45,
++ 47,
++ 49,
++ 54,
++ 58
++ ],
++ "sysroot" :
++ {
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
++ }
++ },
++ {
++ "compileCommandFragments" :
++ [
++ {
++ "fragment" : " -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC"
++ }
++ ],
++ "includes" :
++ [
++ {
++ "backtrace" : 2,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core"
++ }
++ ],
++ "language" : "ASM",
++ "sourceIndexes" :
++ [
++ 60,
++ 61
++ ],
++ "sysroot" :
++ {
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
++ }
++ }
++ ],
++ "id" : "core::@57760688d1f824db5d9c",
++ "name" : "core",
++ "nameOnDisk" : "libcore.a",
++ "paths" :
++ {
++ "build" : "core",
++ "source" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core"
++ },
++ "sourceGroups" :
++ [
++ {
++ "name" : "Header Files",
++ "sourceIndexes" :
++ [
++ 0,
++ 3,
++ 6,
++ 9,
++ 12,
++ 15,
++ 17,
++ 19,
++ 21,
++ 24,
++ 26,
++ 30,
++ 36,
++ 39,
++ 40,
++ 42,
++ 44,
++ 46,
++ 48,
++ 50,
++ 51,
++ 52,
++ 53,
++ 55,
++ 56,
++ 57,
++ 59
++ ]
++ },
++ {
++ "name" : "Source Files",
++ "sourceIndexes" :
++ [
++ 1,
++ 2,
++ 4,
++ 5,
++ 7,
++ 8,
++ 10,
++ 11,
++ 13,
++ 14,
++ 16,
++ 18,
++ 20,
++ 22,
++ 23,
++ 25,
++ 27,
++ 28,
++ 29,
++ 31,
++ 32,
++ 33,
++ 34,
++ 35,
++ 37,
++ 38,
++ 41,
++ 43,
++ 45,
++ 47,
++ 49,
++ 54,
++ 58
++ ]
++ },
++ {
++ "name" : "",
++ "sourceIndexes" :
++ [
++ 60,
++ 61
++ ]
++ }
++ ],
++ "sources" :
++ [
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_Android.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_OSX.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog_Android.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData_OSX.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt_OSX.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder_OSX.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Win32.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Android.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Android.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Linux.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Win32.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_OSX.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock_Win32.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVMetaInfo.hpp",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_core.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_locl.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_cfb128.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_opensslconf.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_locl.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_one.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md32_common.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_arm_arch.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/Checksum.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/crc32_armv8.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/zconf.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/zutil.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.cpp",
++ "sourceGroupIndex" : 1
++ },
++ {
++ "backtrace" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVPredef.h",
++ "sourceGroupIndex" : 0
++ },
++ {
++ "backtrace" : 4,
++ "compileGroupIndex" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S",
++ "sourceGroupIndex" : 2
++ },
++ {
++ "backtrace" : 4,
++ "compileGroupIndex" : 1,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S",
++ "sourceGroupIndex" : 2
++ }
++ ],
++ "type" : "STATIC_LIBRARY"
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/target-rnmmkv-Debug-0134b721e8df58d1deb2.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/target-rnmmkv-Debug-0134b721e8df58d1deb2.json
+new file mode 100644
+index 0000000..03af3e6
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.cmake/api/v1/reply/target-rnmmkv-Debug-0134b721e8df58d1deb2.json
+@@ -0,0 +1,190 @@
++{
++ "artifacts" :
++ [
++ {
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so"
++ }
++ ],
++ "backtrace" : 1,
++ "backtraceGraph" :
++ {
++ "commands" :
++ [
++ "add_library",
++ "target_link_libraries",
++ "set_target_properties"
++ ],
++ "files" :
++ [
++ "CMakeLists.txt"
++ ],
++ "nodes" :
++ [
++ {
++ "file" : 0
++ },
++ {
++ "command" : 0,
++ "file" : 0,
++ "line" : 11,
++ "parent" : 0
++ },
++ {
++ "command" : 1,
++ "file" : 0,
++ "line" : 30,
++ "parent" : 0
++ },
++ {
++ "command" : 2,
++ "file" : 0,
++ "line" : 17,
++ "parent" : 0
++ }
++ ]
++ },
++ "compileGroups" :
++ [
++ {
++ "compileCommandFragments" :
++ [
++ {
++ "fragment" : "-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC"
++ }
++ ],
++ "defines" :
++ [
++ {
++ "define" : "rnmmkv_EXPORTS"
++ }
++ ],
++ "includes" :
++ [
++ {
++ "backtrace" : 2,
++ "path" : "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core"
++ },
++ {
++ "backtrace" : 2,
++ "isSystem" : true,
++ "path" : "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/include"
++ },
++ {
++ "backtrace" : 2,
++ "isSystem" : true,
++ "path" : "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/include"
++ },
++ {
++ "backtrace" : 2,
++ "isSystem" : true,
++ "path" : "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/include"
++ }
++ ],
++ "language" : "CXX",
++ "languageStandard" :
++ {
++ "backtraces" :
++ [
++ 3
++ ],
++ "standard" : "17"
++ },
++ "sourceIndexes" :
++ [
++ 0
++ ],
++ "sysroot" :
++ {
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
++ }
++ }
++ ],
++ "dependencies" :
++ [
++ {
++ "backtrace" : 2,
++ "id" : "core::@57760688d1f824db5d9c"
++ }
++ ],
++ "id" : "rnmmkv::@6890427a1f51a3e7e1df",
++ "link" :
++ {
++ "commandFragments" :
++ [
++ {
++ "fragment" : "-Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments",
++ "role" : "flags"
++ },
++ {
++ "backtrace" : 2,
++ "fragment" : "core/libcore.a",
++ "role" : "libraries"
++ },
++ {
++ "backtrace" : 2,
++ "fragment" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so",
++ "role" : "libraries"
++ },
++ {
++ "backtrace" : 2,
++ "fragment" : "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.arm64-v8a/libfbjni.so",
++ "role" : "libraries"
++ },
++ {
++ "backtrace" : 2,
++ "fragment" : "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/libs/android.arm64-v8a/libjsi.so",
++ "role" : "libraries"
++ },
++ {
++ "backtrace" : 2,
++ "fragment" : "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/libs/android.arm64-v8a/libreactnative.so",
++ "role" : "libraries"
++ },
++ {
++ "backtrace" : 2,
++ "fragment" : "-landroid",
++ "role" : "libraries"
++ },
++ {
++ "fragment" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so",
++ "role" : "libraries"
++ },
++ {
++ "fragment" : "-latomic -lm",
++ "role" : "libraries"
++ }
++ ],
++ "language" : "CXX",
++ "sysroot" :
++ {
++ "path" : "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
++ }
++ },
++ "name" : "rnmmkv",
++ "nameOnDisk" : "librnmmkv.so",
++ "paths" :
++ {
++ "build" : ".",
++ "source" : "."
++ },
++ "sourceGroups" :
++ [
++ {
++ "name" : "Source Files",
++ "sourceIndexes" :
++ [
++ 0
++ ]
++ }
++ ],
++ "sources" :
++ [
++ {
++ "backtrace" : 1,
++ "compileGroupIndex" : 0,
++ "path" : "rnmmkv-adapter.cpp",
++ "sourceGroupIndex" : 0
++ }
++ ],
++ "type" : "SHARED_LIBRARY"
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.ninja_deps b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.ninja_deps
+new file mode 100644
+index 0000000..2043829
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.ninja_deps differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.ninja_log b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.ninja_log
+new file mode 100644
+index 0000000..b7f9462
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/.ninja_log
+@@ -0,0 +1,39 @@
++# ninja log v5
++1 215 1747802889677598620 core/CMakeFiles/core.dir/MMKV_OSX.cpp.o da07b9df5bd10ccc
++1 222 1747802889681723284 core/CMakeFiles/core.dir/MMKV.cpp.o 1808d54a74d65af
++1 223 1747802889678136136 core/CMakeFiles/core.dir/MMKV_Android.cpp.o f2ebf4c76fbaad5a
++1 224 1747802889681606239 core/CMakeFiles/core.dir/MMKV_IO.cpp.o cf8187da0938b5df
++1 224 1747802889677996674 core/CMakeFiles/core.dir/MMKVLog.cpp.o 9bf74317ce32ffc6
++2 225 1747802889681578446 core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o 32e0e5f6f54428d4
++3 225 1747802889678348392 core/CMakeFiles/core.dir/CodedInputData.cpp.o 27bd4b77b1baa844
++3 226 1747802889678263390 core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o 756111422dff3d3f
++4 226 1747802889678147595 core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o 7ef3283d43d1a40d
++4 227 1747802889678184638 core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o 54eabf01b8e76c07
++5 227 1747802889677655914 core/CMakeFiles/core.dir/CodedOutputData.cpp.o 846547eeb72476a2
++6 228 1747802889677753833 core/CMakeFiles/core.dir/KeyValueHolder.cpp.o 10c18ce1cff9b597
++6 230 1747802889678704153 core/CMakeFiles/core.dir/PBUtility.cpp.o c131725682e452d4
++1 230 1747802889683396875 CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o 6149d9a4be17990b
++223 299 1747802889765664767 core/CMakeFiles/core.dir/MMBuffer.cpp.o eee51a8927e0dfab
++222 312 1747802889778952451 core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o 16d0fd15cd19e036
++224 313 1747802889779142540 core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o 38fb26b087a1fbf4
++224 317 1747802889784442489 core/CMakeFiles/core.dir/InterProcessLock.cpp.o 4e953281c51f3cf4
++225 319 1747802889784968212 core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o 486741ae68f3ec05
++230 319 1747802889785657316 core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o affdbafb04258685
++227 322 1747802889786730598 core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o 836473648cdd5991
++225 323 1747802889790035362 core/CMakeFiles/core.dir/MemoryFile.cpp.o 2e27a61f9fad3a50
++222 325 1747802889786677763 core/CMakeFiles/core.dir/MiniPBCoder.cpp.o 6faa9bc3cc97e253
++226 325 1747802889792760526 core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o 8b19abd6e8be1a37
++226 326 1747802889792937740 core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o 162ec30e4cc0defa
++228 327 1747802889788207308 core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o c8badba4d6970931
++228 327 1747802889791172396 core/CMakeFiles/core.dir/ThreadLock.cpp.o a15f55db94ad35cd
++231 328 1747802889791387861 core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o 670192d5e8952658
++313 328 1747802889796113959 core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o c656fe5a91f458de
++317 332 1747802889800585799 core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o 8de52f007a260401
++299 343 1747802889811449579 core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o 161c2c463792ce8
++312 350 1747802889817964188 core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o be325a345735fc93
++319 351 1747802889819520901 core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o 3005644854e524cc
++320 351 1747802889819524818 core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o 7c7abf6fe4235577
++323 366 1747802889834600805 core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o c820628926bbde9
++322 369 1747802889837578268 core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o 8315e1c765e53aa7
++369 432 1747802889901553000 core/libcore.a c3df6e9adba9f773
++432 476 1747802889938398375 /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so 50067b3f82271e5b
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeCache.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeCache.txt
+new file mode 100644
+index 0000000..1c9cb7d
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeCache.txt
+@@ -0,0 +1,469 @@
++# This is the CMakeCache file.
++# For build in directory: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++# It was generated by CMake: /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake
++# You can edit this file to change values found and used by cmake.
++# If you do not want to change any of the values, simply exit the editor.
++# If you do want to change a value, simply edit, save, and exit the editor.
++# The syntax for the file is as follows:
++# KEY:TYPE=VALUE
++# KEY is the name of a variable in the cache.
++# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
++# VALUE is the current value for the KEY.
++
++########################
++# EXTERNAL cache entries
++########################
++
++//No help, variable specified on the command line.
++ANDROID_ABI:UNINITIALIZED=arm64-v8a
++
++//No help, variable specified on the command line.
++ANDROID_NDK:UNINITIALIZED=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006
++
++//No help, variable specified on the command line.
++ANDROID_PLATFORM:UNINITIALIZED=android-24
++
++//No help, variable specified on the command line.
++ANDROID_STL:UNINITIALIZED=c++_shared
++
++//Path to a program.
++CMAKE_ADDR2LINE:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line
++
++//No help, variable specified on the command line.
++CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=arm64-v8a
++
++//No help, variable specified on the command line.
++CMAKE_ANDROID_NDK:UNINITIALIZED=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006
++
++//Archiver
++CMAKE_AR:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar
++
++//ASM compiler
++CMAKE_ASM_COMPILER:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang
++
++//LLVM archiver
++CMAKE_ASM_COMPILER_AR:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar
++
++//Generate index for LLVM archive
++CMAKE_ASM_COMPILER_RANLIB:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib
++
++//Flags used by the compiler during all build types.
++CMAKE_ASM_FLAGS:STRING=
++
++//Flags used by the compiler during debug builds.
++CMAKE_ASM_FLAGS_DEBUG:STRING=
++
++//Flags used by the ASM compiler during MINSIZEREL builds.
++CMAKE_ASM_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
++
++//Flags used by the compiler during release builds.
++CMAKE_ASM_FLAGS_RELEASE:STRING=
++
++//Flags used by the ASM compiler during RELWITHDEBINFO builds.
++CMAKE_ASM_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
++
++//Choose the type of build, options are: None Debug Release RelWithDebInfo
++// MinSizeRel ...
++CMAKE_BUILD_TYPE:STRING=Debug
++
++//LLVM archiver
++CMAKE_CXX_COMPILER_AR:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar
++
++//Compiler launcher for CXX.
++CMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache
++
++//Generate index for LLVM archive
++CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib
++
++//Flags used by the compiler during all build types.
++CMAKE_CXX_FLAGS:STRING=-O3 -frtti -fexceptions -Wall -fstack-protector-all
++
++//Flags used by the compiler during debug builds.
++CMAKE_CXX_FLAGS_DEBUG:STRING=
++
++//Flags used by the CXX compiler during MINSIZEREL builds.
++CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
++
++//Flags used by the compiler during release builds.
++CMAKE_CXX_FLAGS_RELEASE:STRING=
++
++//Flags used by the CXX compiler during RELWITHDEBINFO builds.
++CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
++
++//Libraries linked by default with all C++ applications.
++CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm
++
++//LLVM archiver
++CMAKE_C_COMPILER_AR:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar
++
++//Compiler launcher for C.
++CMAKE_C_COMPILER_LAUNCHER:STRING=ccache
++
++//Generate index for LLVM archive
++CMAKE_C_COMPILER_RANLIB:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib
++
++//Flags used by the compiler during all build types.
++CMAKE_C_FLAGS:STRING=
++
++//Flags used by the compiler during debug builds.
++CMAKE_C_FLAGS_DEBUG:STRING=
++
++//Flags used by the C compiler during MINSIZEREL builds.
++CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
++
++//Flags used by the compiler during release builds.
++CMAKE_C_FLAGS_RELEASE:STRING=
++
++//Flags used by the C compiler during RELWITHDEBINFO builds.
++CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
++
++//Libraries linked by default with all C applications.
++CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm
++
++//Path to a program.
++CMAKE_DLLTOOL:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-dlltool
++
++//Flags used by the linker.
++CMAKE_EXE_LINKER_FLAGS:STRING=
++
++//Flags used by the linker during DEBUG builds.
++CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
++
++//Flags used by the linker during MINSIZEREL builds.
++CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
++
++//Flags used by the linker during RELEASE builds.
++CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
++
++//Flags used by the linker during RELWITHDEBINFO builds.
++CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
++
++//No help, variable specified on the command line.
++CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON
++
++//No help, variable specified on the command line.
++CMAKE_FIND_ROOT_PATH:UNINITIALIZED=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab
++
++//Install path prefix, prepended onto install directories.
++CMAKE_INSTALL_PREFIX:PATH=/usr/local
++
++//No help, variable specified on the command line.
++CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a
++
++//Path to a program.
++CMAKE_LINKER:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld
++
++//No help, variable specified on the command line.
++CMAKE_MAKE_PROGRAM:UNINITIALIZED=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja
++
++//Flags used by the linker during the creation of modules.
++CMAKE_MODULE_LINKER_FLAGS:STRING=
++
++//Flags used by the linker during the creation of modules during
++// DEBUG builds.
++CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
++
++//Flags used by the linker during the creation of modules during
++// MINSIZEREL builds.
++CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
++
++//Flags used by the linker during the creation of modules during
++// RELEASE builds.
++CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
++
++//Flags used by the linker during the creation of modules during
++// RELWITHDEBINFO builds.
++CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
++
++//Path to a program.
++CMAKE_NM:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-nm
++
++//Path to a program.
++CMAKE_OBJCOPY:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objcopy
++
++//Path to a program.
++CMAKE_OBJDUMP:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump
++
++//Value Computed by CMake
++CMAKE_PROJECT_DESCRIPTION:STATIC=
++
++//Value Computed by CMake
++CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
++
++//Value Computed by CMake
++CMAKE_PROJECT_NAME:STATIC=PACKAGE_NAME
++
++//Ranlib
++CMAKE_RANLIB:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib
++
++//Path to a program.
++CMAKE_READELF:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf
++
++//No help, variable specified on the command line.
++CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a
++
++//Flags used by the linker during the creation of dll's.
++CMAKE_SHARED_LINKER_FLAGS:STRING=
++
++//Flags used by the linker during the creation of shared libraries
++// during DEBUG builds.
++CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
++
++//Flags used by the linker during the creation of shared libraries
++// during MINSIZEREL builds.
++CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
++
++//Flags used by the linker during the creation of shared libraries
++// during RELEASE builds.
++CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
++
++//Flags used by the linker during the creation of shared libraries
++// during RELWITHDEBINFO builds.
++CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
++
++//If set, runtime paths are not added when installing shared libraries,
++// but are added when building.
++CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
++
++//If set, runtime paths are not added when using shared libraries.
++CMAKE_SKIP_RPATH:BOOL=NO
++
++//Flags used by the linker during the creation of static libraries
++// during all build types.
++CMAKE_STATIC_LINKER_FLAGS:STRING=
++
++//Flags used by the linker during the creation of static libraries
++// during DEBUG builds.
++CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
++
++//Flags used by the linker during the creation of static libraries
++// during MINSIZEREL builds.
++CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
++
++//Flags used by the linker during the creation of static libraries
++// during RELEASE builds.
++CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
++
++//Flags used by the linker during the creation of static libraries
++// during RELWITHDEBINFO builds.
++CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
++
++//Strip
++CMAKE_STRIP:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-strip
++
++//No help, variable specified on the command line.
++CMAKE_SYSTEM_NAME:UNINITIALIZED=Android
++
++//No help, variable specified on the command line.
++CMAKE_SYSTEM_VERSION:UNINITIALIZED=24
++
++//The CMake toolchain file
++CMAKE_TOOLCHAIN_FILE:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake
++
++//If this value is on, makefiles will be generated without the
++// .SILENT directive, and all commands will be echoed to the console
++// during the make. This is useful for debugging only. With Visual
++// Studio IDE projects all commands are done without /nologo.
++CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
++
++//Value Computed by CMake
++PACKAGE_NAME_BINARY_DIR:STATIC=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++
++//Value Computed by CMake
++PACKAGE_NAME_IS_TOP_LEVEL:STATIC=ON
++
++//Value Computed by CMake
++PACKAGE_NAME_SOURCE_DIR:STATIC=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv
++
++//No help, variable specified on the command line.
++REACT_NATIVE_MINOR_VERSION:UNINITIALIZED=77
++
++//The directory containing a CMake configuration file for ReactAndroid.
++ReactAndroid_DIR:PATH=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid
++
++//Value Computed by CMake
++core_BINARY_DIR:STATIC=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core
++
++//Value Computed by CMake
++core_IS_TOP_LEVEL:STATIC=OFF
++
++//Dependencies for the target
++core_LIB_DEPENDS:STATIC=general;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so;
++
++//Value Computed by CMake
++core_SOURCE_DIR:STATIC=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++
++//The directory containing a CMake configuration file for fbjni.
++fbjni_DIR:PATH=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni
++
++//Path to a library.
++log-lib:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so
++
++//Dependencies for the target
++rnmmkv_LIB_DEPENDS:STATIC=general;core;general;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so;general;fbjni::fbjni;general;ReactAndroid::jsi;general;ReactAndroid::reactnative;general;android;
++
++//Path to a library.
++zlib:FILEPATH=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so
++
++
++########################
++# INTERNAL cache entries
++########################
++
++//ADVANCED property for variable: CMAKE_ADDR2LINE
++CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_AR
++CMAKE_AR-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_COMPILER
++CMAKE_ASM_COMPILER-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_COMPILER_AR
++CMAKE_ASM_COMPILER_AR-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_COMPILER_RANLIB
++CMAKE_ASM_COMPILER_RANLIB-ADVANCED:INTERNAL=1
++CMAKE_ASM_COMPILER_WORKS:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_FLAGS
++CMAKE_ASM_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_FLAGS_DEBUG
++CMAKE_ASM_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_FLAGS_MINSIZEREL
++CMAKE_ASM_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_FLAGS_RELEASE
++CMAKE_ASM_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_ASM_FLAGS_RELWITHDEBINFO
++CMAKE_ASM_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//This is the directory where this CMakeCache.txt was created
++CMAKE_CACHEFILE_DIR:INTERNAL=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++//Major version of cmake used to create the current loaded cache
++CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
++//Minor version of cmake used to create the current loaded cache
++CMAKE_CACHE_MINOR_VERSION:INTERNAL=22
++//Patch version of cmake used to create the current loaded cache
++CMAKE_CACHE_PATCH_VERSION:INTERNAL=1
++//Path to CMake executable.
++CMAKE_COMMAND:INTERNAL=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake
++//Path to cpack program executable.
++CMAKE_CPACK_COMMAND:INTERNAL=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cpack
++//Path to ctest program executable.
++CMAKE_CTEST_COMMAND:INTERNAL=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ctest
++//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
++CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
++CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_FLAGS
++CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
++CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
++CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
++CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
++CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES
++CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_COMPILER_AR
++CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
++CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_FLAGS
++CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
++CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
++CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
++CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
++CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES
++CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_DLLTOOL
++CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
++//Path to cache edit program executable.
++CMAKE_EDIT_COMMAND:INTERNAL=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ccmake
++//Executable file format
++CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
++//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
++CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
++CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
++CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
++CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
++CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//Name of external makefile project generator.
++CMAKE_EXTRA_GENERATOR:INTERNAL=
++//Name of generator.
++CMAKE_GENERATOR:INTERNAL=Ninja
++//Generator instance identifier.
++CMAKE_GENERATOR_INSTANCE:INTERNAL=
++//Name of generator platform.
++CMAKE_GENERATOR_PLATFORM:INTERNAL=
++//Name of generator toolset.
++CMAKE_GENERATOR_TOOLSET:INTERNAL=
++//Source directory with the top level CMakeLists.txt file for this
++// project
++CMAKE_HOME_DIRECTORY:INTERNAL=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv
++//Install .so files without execute permission.
++CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0
++//ADVANCED property for variable: CMAKE_LINKER
++CMAKE_LINKER-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
++CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
++CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
++CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
++CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
++CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_NM
++CMAKE_NM-ADVANCED:INTERNAL=1
++//number of local generators
++CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=2
++//ADVANCED property for variable: CMAKE_OBJCOPY
++CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_OBJDUMP
++CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
++//Platform information initialized
++CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_RANLIB
++CMAKE_RANLIB-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_READELF
++CMAKE_READELF-ADVANCED:INTERNAL=1
++//Path to CMake installation.
++CMAKE_ROOT:INTERNAL=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22
++//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
++CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
++CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
++CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
++CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
++CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
++CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_SKIP_RPATH
++CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
++CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
++CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
++CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
++CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
++CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
++//ADVANCED property for variable: CMAKE_STRIP
++CMAKE_STRIP-ADVANCED:INTERNAL=1
++//uname command
++CMAKE_UNAME:INTERNAL=/usr/bin/uname
++//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
++CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
++
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeASMCompiler.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeASMCompiler.cmake
+new file mode 100644
+index 0000000..22b34cd
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeASMCompiler.cmake
+@@ -0,0 +1,20 @@
++set(CMAKE_ASM_COMPILER "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang")
++set(CMAKE_ASM_COMPILER_ARG1 "")
++set(CMAKE_AR "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar")
++set(CMAKE_ASM_COMPILER_AR "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar")
++set(CMAKE_RANLIB "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib")
++set(CMAKE_ASM_COMPILER_RANLIB "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib")
++set(CMAKE_LINKER "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld")
++set(CMAKE_MT "")
++set(CMAKE_ASM_COMPILER_LOADED 1)
++set(CMAKE_ASM_COMPILER_ID "Clang")
++set(CMAKE_ASM_COMPILER_VERSION "")
++set(CMAKE_ASM_COMPILER_ENV_VAR "ASM")
++set(CMAKE_ASM_COMPILER_ID_VENDOR_MATCH [==[clang version]==])
++
++
++
++set(CMAKE_ASM_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
++set(CMAKE_ASM_LINKER_PREFERENCE 0)
++
++
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake
+new file mode 100644
+index 0000000..9360f55
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake
+@@ -0,0 +1,72 @@
++set(CMAKE_C_COMPILER "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang")
++set(CMAKE_C_COMPILER_ARG1 "")
++set(CMAKE_C_COMPILER_ID "Clang")
++set(CMAKE_C_COMPILER_VERSION "18.0.3")
++set(CMAKE_C_COMPILER_VERSION_INTERNAL "")
++set(CMAKE_C_COMPILER_WRAPPER "")
++set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17")
++set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON")
++set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23")
++set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes")
++set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros")
++set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert")
++set(CMAKE_C17_COMPILE_FEATURES "c_std_17")
++set(CMAKE_C23_COMPILE_FEATURES "c_std_23")
++
++set(CMAKE_C_PLATFORM_ID "Linux")
++set(CMAKE_C_SIMULATE_ID "")
++set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU")
++set(CMAKE_C_SIMULATE_VERSION "")
++
++
++
++
++set(CMAKE_AR "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar")
++set(CMAKE_C_COMPILER_AR "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar")
++set(CMAKE_RANLIB "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib")
++set(CMAKE_C_COMPILER_RANLIB "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib")
++set(CMAKE_LINKER "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld")
++set(CMAKE_MT "")
++set(CMAKE_COMPILER_IS_GNUCC )
++set(CMAKE_C_COMPILER_LOADED 1)
++set(CMAKE_C_COMPILER_WORKS TRUE)
++set(CMAKE_C_ABI_COMPILED TRUE)
++
++set(CMAKE_C_COMPILER_ENV_VAR "CC")
++
++set(CMAKE_C_COMPILER_ID_RUN 1)
++set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
++set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
++set(CMAKE_C_LINKER_PREFERENCE 10)
++
++# Save compiler ABI information.
++set(CMAKE_C_SIZEOF_DATA_PTR "8")
++set(CMAKE_C_COMPILER_ABI "ELF")
++set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN")
++set(CMAKE_C_LIBRARY_ARCHITECTURE "")
++
++if(CMAKE_C_SIZEOF_DATA_PTR)
++ set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
++endif()
++
++if(CMAKE_C_COMPILER_ABI)
++ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
++endif()
++
++if(CMAKE_C_LIBRARY_ARCHITECTURE)
++ set(CMAKE_LIBRARY_ARCHITECTURE "")
++endif()
++
++set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "")
++if(CMAKE_C_CL_SHOWINCLUDES_PREFIX)
++ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}")
++endif()
++
++
++
++
++
++set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include")
++set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl")
++set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib")
++set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake
+new file mode 100644
+index 0000000..3bd2031
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake
+@@ -0,0 +1,83 @@
++set(CMAKE_CXX_COMPILER "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++")
++set(CMAKE_CXX_COMPILER_ARG1 "")
++set(CMAKE_CXX_COMPILER_ID "Clang")
++set(CMAKE_CXX_COMPILER_VERSION "18.0.3")
++set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "")
++set(CMAKE_CXX_COMPILER_WRAPPER "")
++set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17")
++set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON")
++set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23")
++set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters")
++set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates")
++set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates")
++set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17")
++set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20")
++set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23")
++
++set(CMAKE_CXX_PLATFORM_ID "Linux")
++set(CMAKE_CXX_SIMULATE_ID "")
++set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU")
++set(CMAKE_CXX_SIMULATE_VERSION "")
++
++
++
++
++set(CMAKE_AR "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar")
++set(CMAKE_CXX_COMPILER_AR "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar")
++set(CMAKE_RANLIB "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib")
++set(CMAKE_CXX_COMPILER_RANLIB "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib")
++set(CMAKE_LINKER "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld")
++set(CMAKE_MT "")
++set(CMAKE_COMPILER_IS_GNUCXX )
++set(CMAKE_CXX_COMPILER_LOADED 1)
++set(CMAKE_CXX_COMPILER_WORKS TRUE)
++set(CMAKE_CXX_ABI_COMPILED TRUE)
++
++set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
++
++set(CMAKE_CXX_COMPILER_ID_RUN 1)
++set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm)
++set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
++
++foreach (lang C OBJC OBJCXX)
++ if (CMAKE_${lang}_COMPILER_ID_RUN)
++ foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
++ list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
++ endforeach()
++ endif()
++endforeach()
++
++set(CMAKE_CXX_LINKER_PREFERENCE 30)
++set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
++
++# Save compiler ABI information.
++set(CMAKE_CXX_SIZEOF_DATA_PTR "8")
++set(CMAKE_CXX_COMPILER_ABI "ELF")
++set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN")
++set(CMAKE_CXX_LIBRARY_ARCHITECTURE "")
++
++if(CMAKE_CXX_SIZEOF_DATA_PTR)
++ set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
++endif()
++
++if(CMAKE_CXX_COMPILER_ABI)
++ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
++endif()
++
++if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
++ set(CMAKE_LIBRARY_ARCHITECTURE "")
++endif()
++
++set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "")
++if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX)
++ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}")
++endif()
++
++
++
++
++
++set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include")
++set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl")
++set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib")
++set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin
+new file mode 100755
+index 0000000..af27b9a
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin
+new file mode 100755
+index 0000000..6181ba4
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_CXX.bin differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake
+new file mode 100644
+index 0000000..d651da5
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake
+@@ -0,0 +1,15 @@
++set(CMAKE_HOST_SYSTEM "Darwin-24.3.0")
++set(CMAKE_HOST_SYSTEM_NAME "Darwin")
++set(CMAKE_HOST_SYSTEM_VERSION "24.3.0")
++set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64")
++
++include("/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake")
++
++set(CMAKE_SYSTEM "Android-1")
++set(CMAKE_SYSTEM_NAME "Android")
++set(CMAKE_SYSTEM_VERSION "1")
++set(CMAKE_SYSTEM_PROCESSOR "aarch64")
++
++set(CMAKE_CROSSCOMPILING "TRUE")
++
++set(CMAKE_SYSTEM_LOADED 1)
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c
+new file mode 100644
+index 0000000..41b99d7
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c
+@@ -0,0 +1,803 @@
++#ifdef __cplusplus
++# error "A C++ compiler has been selected for C."
++#endif
++
++#if defined(__18CXX)
++# define ID_VOID_MAIN
++#endif
++#if defined(__CLASSIC_C__)
++/* cv-qualifiers did not exist in K&R C */
++# define const
++# define volatile
++#endif
++
++#if !defined(__has_include)
++/* If the compiler does not have __has_include, pretend the answer is
++ always no. */
++# define __has_include(x) 0
++#endif
++
++
++/* Version number components: V=Version, R=Revision, P=Patch
++ Version date components: YYYY=Year, MM=Month, DD=Day */
++
++#if defined(__INTEL_COMPILER) || defined(__ICC)
++# define COMPILER_ID "Intel"
++# if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++# endif
++# if defined(__GNUC__)
++# define SIMULATE_ID "GNU"
++# endif
++ /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
++ except that a few beta releases use the old format with V=2021. */
++# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
++# if defined(__INTEL_COMPILER_UPDATE)
++# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
++# else
++# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
++# endif
++# else
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
++ /* The third version component from --version is an update index,
++ but no macro is provided for it. */
++# define COMPILER_VERSION_PATCH DEC(0)
++# endif
++# if defined(__INTEL_COMPILER_BUILD_DATE)
++ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
++# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
++# endif
++# if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++# endif
++# if defined(__GNUC__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
++# elif defined(__GNUG__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
++# endif
++# if defined(__GNUC_MINOR__)
++# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
++# endif
++# if defined(__GNUC_PATCHLEVEL__)
++# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
++# endif
++
++#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
++# define COMPILER_ID "IntelLLVM"
++#if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++#endif
++#if defined(__GNUC__)
++# define SIMULATE_ID "GNU"
++#endif
++/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
++ * later. Look for 6 digit vs. 8 digit version number to decide encoding.
++ * VVVV is no smaller than the current year when a version is released.
++ */
++#if __INTEL_LLVM_COMPILER < 1000000L
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
++#else
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
++# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
++#endif
++#if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++#endif
++#if defined(__GNUC__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
++#elif defined(__GNUG__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
++#endif
++#if defined(__GNUC_MINOR__)
++# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
++#endif
++#if defined(__GNUC_PATCHLEVEL__)
++# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
++#endif
++
++#elif defined(__PATHCC__)
++# define COMPILER_ID "PathScale"
++# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
++# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
++# if defined(__PATHCC_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
++# endif
++
++#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
++# define COMPILER_ID "Embarcadero"
++# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
++# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
++# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
++
++#elif defined(__BORLANDC__)
++# define COMPILER_ID "Borland"
++ /* __BORLANDC__ = 0xVRR */
++# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
++# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
++
++#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
++# define COMPILER_ID "Watcom"
++ /* __WATCOMC__ = VVRR */
++# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
++# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
++# if (__WATCOMC__ % 10) > 0
++# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
++# endif
++
++#elif defined(__WATCOMC__)
++# define COMPILER_ID "OpenWatcom"
++ /* __WATCOMC__ = VVRP + 1100 */
++# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
++# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
++# if (__WATCOMC__ % 10) > 0
++# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
++# endif
++
++#elif defined(__SUNPRO_C)
++# define COMPILER_ID "SunPro"
++# if __SUNPRO_C >= 0x5100
++ /* __SUNPRO_C = 0xVRRP */
++# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
++# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
++# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
++# else
++ /* __SUNPRO_CC = 0xVRP */
++# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
++# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
++# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
++# endif
++
++#elif defined(__HP_cc)
++# define COMPILER_ID "HP"
++ /* __HP_cc = VVRRPP */
++# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
++# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
++# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
++
++#elif defined(__DECC)
++# define COMPILER_ID "Compaq"
++ /* __DECC_VER = VVRRTPPPP */
++# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
++# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
++# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
++
++#elif defined(__IBMC__) && defined(__COMPILER_VER__)
++# define COMPILER_ID "zOS"
++ /* __IBMC__ = VRP */
++# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
++# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
++
++#elif defined(__ibmxl__) && defined(__clang__)
++# define COMPILER_ID "XLClang"
++# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
++# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
++# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
++# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
++
++
++#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800
++# define COMPILER_ID "XL"
++ /* __IBMC__ = VRP */
++# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
++# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
++
++#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800
++# define COMPILER_ID "VisualAge"
++ /* __IBMC__ = VRP */
++# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
++# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
++
++#elif defined(__NVCOMPILER)
++# define COMPILER_ID "NVHPC"
++# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
++# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
++# if defined(__NVCOMPILER_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
++# endif
++
++#elif defined(__PGI)
++# define COMPILER_ID "PGI"
++# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
++# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
++# if defined(__PGIC_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
++# endif
++
++#elif defined(_CRAYC)
++# define COMPILER_ID "Cray"
++# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
++# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
++
++#elif defined(__TI_COMPILER_VERSION__)
++# define COMPILER_ID "TI"
++ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
++# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
++# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
++# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
++
++#elif defined(__CLANG_FUJITSU)
++# define COMPILER_ID "FujitsuClang"
++# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
++# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
++# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
++# define COMPILER_VERSION_INTERNAL_STR __clang_version__
++
++
++#elif defined(__FUJITSU)
++# define COMPILER_ID "Fujitsu"
++# if defined(__FCC_version__)
++# define COMPILER_VERSION __FCC_version__
++# elif defined(__FCC_major__)
++# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
++# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
++# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
++# endif
++# if defined(__fcc_version)
++# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
++# elif defined(__FCC_VERSION)
++# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
++# endif
++
++
++#elif defined(__ghs__)
++# define COMPILER_ID "GHS"
++/* __GHS_VERSION_NUMBER = VVVVRP */
++# ifdef __GHS_VERSION_NUMBER
++# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
++# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
++# endif
++
++#elif defined(__TINYC__)
++# define COMPILER_ID "TinyCC"
++
++#elif defined(__BCC__)
++# define COMPILER_ID "Bruce"
++
++#elif defined(__SCO_VERSION__)
++# define COMPILER_ID "SCO"
++
++#elif defined(__ARMCC_VERSION) && !defined(__clang__)
++# define COMPILER_ID "ARMCC"
++#if __ARMCC_VERSION >= 1000000
++ /* __ARMCC_VERSION = VRRPPPP */
++ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
++ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
++ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
++#else
++ /* __ARMCC_VERSION = VRPPPP */
++ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
++ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
++ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
++#endif
++
++
++#elif defined(__clang__) && defined(__apple_build_version__)
++# define COMPILER_ID "AppleClang"
++# if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++# endif
++# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
++# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
++# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
++# if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++# endif
++# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
++
++#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
++# define COMPILER_ID "ARMClang"
++ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
++ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
++ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
++# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
++
++#elif defined(__clang__)
++# define COMPILER_ID "Clang"
++# if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++# endif
++# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
++# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
++# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
++# if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++# endif
++
++#elif defined(__GNUC__)
++# define COMPILER_ID "GNU"
++# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
++# if defined(__GNUC_MINOR__)
++# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
++# endif
++# if defined(__GNUC_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
++# endif
++
++#elif defined(_MSC_VER)
++# define COMPILER_ID "MSVC"
++ /* _MSC_VER = VVRR */
++# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
++# if defined(_MSC_FULL_VER)
++# if _MSC_VER >= 1400
++ /* _MSC_FULL_VER = VVRRPPPPP */
++# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
++# else
++ /* _MSC_FULL_VER = VVRRPPPP */
++# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
++# endif
++# endif
++# if defined(_MSC_BUILD)
++# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
++# endif
++
++#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
++# define COMPILER_ID "ADSP"
++#if defined(__VISUALDSPVERSION__)
++ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
++# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
++# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
++# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
++#endif
++
++#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
++# define COMPILER_ID "IAR"
++# if defined(__VER__) && defined(__ICCARM__)
++# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
++# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
++# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
++# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
++# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
++# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
++# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
++# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
++# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
++# endif
++
++#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC)
++# define COMPILER_ID "SDCC"
++# if defined(__SDCC_VERSION_MAJOR)
++# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR)
++# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR)
++# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH)
++# else
++ /* SDCC = VRP */
++# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
++# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
++# endif
++
++
++/* These compilers are either not known or too old to define an
++ identification macro. Try to identify the platform and guess that
++ it is the native compiler. */
++#elif defined(__hpux) || defined(__hpua)
++# define COMPILER_ID "HP"
++
++#else /* unknown compiler */
++# define COMPILER_ID ""
++#endif
++
++/* Construct the string literal in pieces to prevent the source from
++ getting matched. Store it in a pointer rather than an array
++ because some compilers will just produce instructions to fill the
++ array rather than assigning a pointer to a static array. */
++char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
++#ifdef SIMULATE_ID
++char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
++#endif
++
++#ifdef __QNXNTO__
++char const* qnxnto = "INFO" ":" "qnxnto[]";
++#endif
++
++#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
++char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
++#endif
++
++#define STRINGIFY_HELPER(X) #X
++#define STRINGIFY(X) STRINGIFY_HELPER(X)
++
++/* Identify known platforms by name. */
++#if defined(__linux) || defined(__linux__) || defined(linux)
++# define PLATFORM_ID "Linux"
++
++#elif defined(__MSYS__)
++# define PLATFORM_ID "MSYS"
++
++#elif defined(__CYGWIN__)
++# define PLATFORM_ID "Cygwin"
++
++#elif defined(__MINGW32__)
++# define PLATFORM_ID "MinGW"
++
++#elif defined(__APPLE__)
++# define PLATFORM_ID "Darwin"
++
++#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
++# define PLATFORM_ID "Windows"
++
++#elif defined(__FreeBSD__) || defined(__FreeBSD)
++# define PLATFORM_ID "FreeBSD"
++
++#elif defined(__NetBSD__) || defined(__NetBSD)
++# define PLATFORM_ID "NetBSD"
++
++#elif defined(__OpenBSD__) || defined(__OPENBSD)
++# define PLATFORM_ID "OpenBSD"
++
++#elif defined(__sun) || defined(sun)
++# define PLATFORM_ID "SunOS"
++
++#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
++# define PLATFORM_ID "AIX"
++
++#elif defined(__hpux) || defined(__hpux__)
++# define PLATFORM_ID "HP-UX"
++
++#elif defined(__HAIKU__)
++# define PLATFORM_ID "Haiku"
++
++#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
++# define PLATFORM_ID "BeOS"
++
++#elif defined(__QNX__) || defined(__QNXNTO__)
++# define PLATFORM_ID "QNX"
++
++#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
++# define PLATFORM_ID "Tru64"
++
++#elif defined(__riscos) || defined(__riscos__)
++# define PLATFORM_ID "RISCos"
++
++#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
++# define PLATFORM_ID "SINIX"
++
++#elif defined(__UNIX_SV__)
++# define PLATFORM_ID "UNIX_SV"
++
++#elif defined(__bsdos__)
++# define PLATFORM_ID "BSDOS"
++
++#elif defined(_MPRAS) || defined(MPRAS)
++# define PLATFORM_ID "MP-RAS"
++
++#elif defined(__osf) || defined(__osf__)
++# define PLATFORM_ID "OSF1"
++
++#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
++# define PLATFORM_ID "SCO_SV"
++
++#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
++# define PLATFORM_ID "ULTRIX"
++
++#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
++# define PLATFORM_ID "Xenix"
++
++#elif defined(__WATCOMC__)
++# if defined(__LINUX__)
++# define PLATFORM_ID "Linux"
++
++# elif defined(__DOS__)
++# define PLATFORM_ID "DOS"
++
++# elif defined(__OS2__)
++# define PLATFORM_ID "OS2"
++
++# elif defined(__WINDOWS__)
++# define PLATFORM_ID "Windows3x"
++
++# elif defined(__VXWORKS__)
++# define PLATFORM_ID "VxWorks"
++
++# else /* unknown platform */
++# define PLATFORM_ID
++# endif
++
++#elif defined(__INTEGRITY)
++# if defined(INT_178B)
++# define PLATFORM_ID "Integrity178"
++
++# else /* regular Integrity */
++# define PLATFORM_ID "Integrity"
++# endif
++
++#else /* unknown platform */
++# define PLATFORM_ID
++
++#endif
++
++/* For windows compilers MSVC and Intel we can determine
++ the architecture of the compiler being used. This is because
++ the compilers do not have flags that can change the architecture,
++ but rather depend on which compiler is being used
++*/
++#if defined(_WIN32) && defined(_MSC_VER)
++# if defined(_M_IA64)
++# define ARCHITECTURE_ID "IA64"
++
++# elif defined(_M_ARM64EC)
++# define ARCHITECTURE_ID "ARM64EC"
++
++# elif defined(_M_X64) || defined(_M_AMD64)
++# define ARCHITECTURE_ID "x64"
++
++# elif defined(_M_IX86)
++# define ARCHITECTURE_ID "X86"
++
++# elif defined(_M_ARM64)
++# define ARCHITECTURE_ID "ARM64"
++
++# elif defined(_M_ARM)
++# if _M_ARM == 4
++# define ARCHITECTURE_ID "ARMV4I"
++# elif _M_ARM == 5
++# define ARCHITECTURE_ID "ARMV5I"
++# else
++# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
++# endif
++
++# elif defined(_M_MIPS)
++# define ARCHITECTURE_ID "MIPS"
++
++# elif defined(_M_SH)
++# define ARCHITECTURE_ID "SHx"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__WATCOMC__)
++# if defined(_M_I86)
++# define ARCHITECTURE_ID "I86"
++
++# elif defined(_M_IX86)
++# define ARCHITECTURE_ID "X86"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
++# if defined(__ICCARM__)
++# define ARCHITECTURE_ID "ARM"
++
++# elif defined(__ICCRX__)
++# define ARCHITECTURE_ID "RX"
++
++# elif defined(__ICCRH850__)
++# define ARCHITECTURE_ID "RH850"
++
++# elif defined(__ICCRL78__)
++# define ARCHITECTURE_ID "RL78"
++
++# elif defined(__ICCRISCV__)
++# define ARCHITECTURE_ID "RISCV"
++
++# elif defined(__ICCAVR__)
++# define ARCHITECTURE_ID "AVR"
++
++# elif defined(__ICC430__)
++# define ARCHITECTURE_ID "MSP430"
++
++# elif defined(__ICCV850__)
++# define ARCHITECTURE_ID "V850"
++
++# elif defined(__ICC8051__)
++# define ARCHITECTURE_ID "8051"
++
++# elif defined(__ICCSTM8__)
++# define ARCHITECTURE_ID "STM8"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__ghs__)
++# if defined(__PPC64__)
++# define ARCHITECTURE_ID "PPC64"
++
++# elif defined(__ppc__)
++# define ARCHITECTURE_ID "PPC"
++
++# elif defined(__ARM__)
++# define ARCHITECTURE_ID "ARM"
++
++# elif defined(__x86_64__)
++# define ARCHITECTURE_ID "x64"
++
++# elif defined(__i386__)
++# define ARCHITECTURE_ID "X86"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__TI_COMPILER_VERSION__)
++# if defined(__TI_ARM__)
++# define ARCHITECTURE_ID "ARM"
++
++# elif defined(__MSP430__)
++# define ARCHITECTURE_ID "MSP430"
++
++# elif defined(__TMS320C28XX__)
++# define ARCHITECTURE_ID "TMS320C28x"
++
++# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
++# define ARCHITECTURE_ID "TMS320C6x"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#else
++# define ARCHITECTURE_ID
++#endif
++
++/* Convert integer to decimal digit literals. */
++#define DEC(n) \
++ ('0' + (((n) / 10000000)%10)), \
++ ('0' + (((n) / 1000000)%10)), \
++ ('0' + (((n) / 100000)%10)), \
++ ('0' + (((n) / 10000)%10)), \
++ ('0' + (((n) / 1000)%10)), \
++ ('0' + (((n) / 100)%10)), \
++ ('0' + (((n) / 10)%10)), \
++ ('0' + ((n) % 10))
++
++/* Convert integer to hex digit literals. */
++#define HEX(n) \
++ ('0' + ((n)>>28 & 0xF)), \
++ ('0' + ((n)>>24 & 0xF)), \
++ ('0' + ((n)>>20 & 0xF)), \
++ ('0' + ((n)>>16 & 0xF)), \
++ ('0' + ((n)>>12 & 0xF)), \
++ ('0' + ((n)>>8 & 0xF)), \
++ ('0' + ((n)>>4 & 0xF)), \
++ ('0' + ((n) & 0xF))
++
++/* Construct a string literal encoding the version number. */
++#ifdef COMPILER_VERSION
++char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
++
++/* Construct a string literal encoding the version number components. */
++#elif defined(COMPILER_VERSION_MAJOR)
++char const info_version[] = {
++ 'I', 'N', 'F', 'O', ':',
++ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
++ COMPILER_VERSION_MAJOR,
++# ifdef COMPILER_VERSION_MINOR
++ '.', COMPILER_VERSION_MINOR,
++# ifdef COMPILER_VERSION_PATCH
++ '.', COMPILER_VERSION_PATCH,
++# ifdef COMPILER_VERSION_TWEAK
++ '.', COMPILER_VERSION_TWEAK,
++# endif
++# endif
++# endif
++ ']','\0'};
++#endif
++
++/* Construct a string literal encoding the internal version number. */
++#ifdef COMPILER_VERSION_INTERNAL
++char const info_version_internal[] = {
++ 'I', 'N', 'F', 'O', ':',
++ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
++ 'i','n','t','e','r','n','a','l','[',
++ COMPILER_VERSION_INTERNAL,']','\0'};
++#elif defined(COMPILER_VERSION_INTERNAL_STR)
++char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
++#endif
++
++/* Construct a string literal encoding the version number components. */
++#ifdef SIMULATE_VERSION_MAJOR
++char const info_simulate_version[] = {
++ 'I', 'N', 'F', 'O', ':',
++ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
++ SIMULATE_VERSION_MAJOR,
++# ifdef SIMULATE_VERSION_MINOR
++ '.', SIMULATE_VERSION_MINOR,
++# ifdef SIMULATE_VERSION_PATCH
++ '.', SIMULATE_VERSION_PATCH,
++# ifdef SIMULATE_VERSION_TWEAK
++ '.', SIMULATE_VERSION_TWEAK,
++# endif
++# endif
++# endif
++ ']','\0'};
++#endif
++
++/* Construct the string literal in pieces to prevent the source from
++ getting matched. Store it in a pointer rather than an array
++ because some compilers will just produce instructions to fill the
++ array rather than assigning a pointer to a static array. */
++char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
++char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
++
++
++
++#if !defined(__STDC__) && !defined(__clang__)
++# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__)
++# define C_VERSION "90"
++# else
++# define C_VERSION
++# endif
++#elif __STDC_VERSION__ > 201710L
++# define C_VERSION "23"
++#elif __STDC_VERSION__ >= 201710L
++# define C_VERSION "17"
++#elif __STDC_VERSION__ >= 201000L
++# define C_VERSION "11"
++#elif __STDC_VERSION__ >= 199901L
++# define C_VERSION "99"
++#else
++# define C_VERSION "90"
++#endif
++const char* info_language_standard_default =
++ "INFO" ":" "standard_default[" C_VERSION "]";
++
++const char* info_language_extensions_default = "INFO" ":" "extensions_default["
++/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */
++#if (defined(__clang__) || defined(__GNUC__) || \
++ defined(__TI_COMPILER_VERSION__)) && \
++ !defined(__STRICT_ANSI__) && !defined(_MSC_VER)
++ "ON"
++#else
++ "OFF"
++#endif
++"]";
++
++/*--------------------------------------------------------------------------*/
++
++#ifdef ID_VOID_MAIN
++void main() {}
++#else
++# if defined(__CLASSIC_C__)
++int main(argc, argv) int argc; char *argv[];
++# else
++int main(int argc, char* argv[])
++# endif
++{
++ int require = 0;
++ require += info_compiler[argc];
++ require += info_platform[argc];
++ require += info_arch[argc];
++#ifdef COMPILER_VERSION_MAJOR
++ require += info_version[argc];
++#endif
++#ifdef COMPILER_VERSION_INTERNAL
++ require += info_version_internal[argc];
++#endif
++#ifdef SIMULATE_ID
++ require += info_simulate[argc];
++#endif
++#ifdef SIMULATE_VERSION_MAJOR
++ require += info_simulate_version[argc];
++#endif
++#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
++ require += info_cray[argc];
++#endif
++ require += info_language_standard_default[argc];
++ require += info_language_extensions_default[argc];
++ (void)argv;
++ return require;
++}
++#endif
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o
+new file mode 100644
+index 0000000..6442261
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp
+new file mode 100644
+index 0000000..25c62a8
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.cpp
+@@ -0,0 +1,791 @@
++/* This source file must have a .cpp extension so that all C++ compilers
++ recognize the extension without flags. Borland does not know .cxx for
++ example. */
++#ifndef __cplusplus
++# error "A C compiler has been selected for C++."
++#endif
++
++#if !defined(__has_include)
++/* If the compiler does not have __has_include, pretend the answer is
++ always no. */
++# define __has_include(x) 0
++#endif
++
++
++/* Version number components: V=Version, R=Revision, P=Patch
++ Version date components: YYYY=Year, MM=Month, DD=Day */
++
++#if defined(__COMO__)
++# define COMPILER_ID "Comeau"
++ /* __COMO_VERSION__ = VRR */
++# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
++# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
++
++#elif defined(__INTEL_COMPILER) || defined(__ICC)
++# define COMPILER_ID "Intel"
++# if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++# endif
++# if defined(__GNUC__)
++# define SIMULATE_ID "GNU"
++# endif
++ /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
++ except that a few beta releases use the old format with V=2021. */
++# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
++# if defined(__INTEL_COMPILER_UPDATE)
++# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
++# else
++# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
++# endif
++# else
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
++ /* The third version component from --version is an update index,
++ but no macro is provided for it. */
++# define COMPILER_VERSION_PATCH DEC(0)
++# endif
++# if defined(__INTEL_COMPILER_BUILD_DATE)
++ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
++# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
++# endif
++# if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++# endif
++# if defined(__GNUC__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
++# elif defined(__GNUG__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
++# endif
++# if defined(__GNUC_MINOR__)
++# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
++# endif
++# if defined(__GNUC_PATCHLEVEL__)
++# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
++# endif
++
++#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
++# define COMPILER_ID "IntelLLVM"
++#if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++#endif
++#if defined(__GNUC__)
++# define SIMULATE_ID "GNU"
++#endif
++/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
++ * later. Look for 6 digit vs. 8 digit version number to decide encoding.
++ * VVVV is no smaller than the current year when a version is released.
++ */
++#if __INTEL_LLVM_COMPILER < 1000000L
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
++#else
++# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
++# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
++# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
++#endif
++#if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++#endif
++#if defined(__GNUC__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
++#elif defined(__GNUG__)
++# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
++#endif
++#if defined(__GNUC_MINOR__)
++# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
++#endif
++#if defined(__GNUC_PATCHLEVEL__)
++# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
++#endif
++
++#elif defined(__PATHCC__)
++# define COMPILER_ID "PathScale"
++# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
++# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
++# if defined(__PATHCC_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
++# endif
++
++#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
++# define COMPILER_ID "Embarcadero"
++# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
++# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
++# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
++
++#elif defined(__BORLANDC__)
++# define COMPILER_ID "Borland"
++ /* __BORLANDC__ = 0xVRR */
++# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
++# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
++
++#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
++# define COMPILER_ID "Watcom"
++ /* __WATCOMC__ = VVRR */
++# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
++# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
++# if (__WATCOMC__ % 10) > 0
++# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
++# endif
++
++#elif defined(__WATCOMC__)
++# define COMPILER_ID "OpenWatcom"
++ /* __WATCOMC__ = VVRP + 1100 */
++# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
++# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
++# if (__WATCOMC__ % 10) > 0
++# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
++# endif
++
++#elif defined(__SUNPRO_CC)
++# define COMPILER_ID "SunPro"
++# if __SUNPRO_CC >= 0x5100
++ /* __SUNPRO_CC = 0xVRRP */
++# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
++# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
++# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
++# else
++ /* __SUNPRO_CC = 0xVRP */
++# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
++# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
++# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
++# endif
++
++#elif defined(__HP_aCC)
++# define COMPILER_ID "HP"
++ /* __HP_aCC = VVRRPP */
++# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
++# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
++# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
++
++#elif defined(__DECCXX)
++# define COMPILER_ID "Compaq"
++ /* __DECCXX_VER = VVRRTPPPP */
++# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
++# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
++# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
++
++#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
++# define COMPILER_ID "zOS"
++ /* __IBMCPP__ = VRP */
++# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
++# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
++
++#elif defined(__ibmxl__) && defined(__clang__)
++# define COMPILER_ID "XLClang"
++# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
++# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
++# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
++# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
++
++
++#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
++# define COMPILER_ID "XL"
++ /* __IBMCPP__ = VRP */
++# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
++# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
++
++#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
++# define COMPILER_ID "VisualAge"
++ /* __IBMCPP__ = VRP */
++# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
++# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
++
++#elif defined(__NVCOMPILER)
++# define COMPILER_ID "NVHPC"
++# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
++# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
++# if defined(__NVCOMPILER_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
++# endif
++
++#elif defined(__PGI)
++# define COMPILER_ID "PGI"
++# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
++# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
++# if defined(__PGIC_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
++# endif
++
++#elif defined(_CRAYC)
++# define COMPILER_ID "Cray"
++# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
++# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
++
++#elif defined(__TI_COMPILER_VERSION__)
++# define COMPILER_ID "TI"
++ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
++# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
++# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
++# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
++
++#elif defined(__CLANG_FUJITSU)
++# define COMPILER_ID "FujitsuClang"
++# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
++# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
++# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
++# define COMPILER_VERSION_INTERNAL_STR __clang_version__
++
++
++#elif defined(__FUJITSU)
++# define COMPILER_ID "Fujitsu"
++# if defined(__FCC_version__)
++# define COMPILER_VERSION __FCC_version__
++# elif defined(__FCC_major__)
++# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
++# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
++# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
++# endif
++# if defined(__fcc_version)
++# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
++# elif defined(__FCC_VERSION)
++# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
++# endif
++
++
++#elif defined(__ghs__)
++# define COMPILER_ID "GHS"
++/* __GHS_VERSION_NUMBER = VVVVRP */
++# ifdef __GHS_VERSION_NUMBER
++# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
++# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
++# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
++# endif
++
++#elif defined(__SCO_VERSION__)
++# define COMPILER_ID "SCO"
++
++#elif defined(__ARMCC_VERSION) && !defined(__clang__)
++# define COMPILER_ID "ARMCC"
++#if __ARMCC_VERSION >= 1000000
++ /* __ARMCC_VERSION = VRRPPPP */
++ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
++ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
++ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
++#else
++ /* __ARMCC_VERSION = VRPPPP */
++ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
++ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
++ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
++#endif
++
++
++#elif defined(__clang__) && defined(__apple_build_version__)
++# define COMPILER_ID "AppleClang"
++# if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++# endif
++# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
++# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
++# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
++# if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++# endif
++# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
++
++#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
++# define COMPILER_ID "ARMClang"
++ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
++ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
++ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
++# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
++
++#elif defined(__clang__)
++# define COMPILER_ID "Clang"
++# if defined(_MSC_VER)
++# define SIMULATE_ID "MSVC"
++# endif
++# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
++# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
++# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
++# if defined(_MSC_VER)
++ /* _MSC_VER = VVRR */
++# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
++# endif
++
++#elif defined(__GNUC__) || defined(__GNUG__)
++# define COMPILER_ID "GNU"
++# if defined(__GNUC__)
++# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
++# else
++# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
++# endif
++# if defined(__GNUC_MINOR__)
++# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
++# endif
++# if defined(__GNUC_PATCHLEVEL__)
++# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
++# endif
++
++#elif defined(_MSC_VER)
++# define COMPILER_ID "MSVC"
++ /* _MSC_VER = VVRR */
++# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
++# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
++# if defined(_MSC_FULL_VER)
++# if _MSC_VER >= 1400
++ /* _MSC_FULL_VER = VVRRPPPPP */
++# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
++# else
++ /* _MSC_FULL_VER = VVRRPPPP */
++# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
++# endif
++# endif
++# if defined(_MSC_BUILD)
++# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
++# endif
++
++#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
++# define COMPILER_ID "ADSP"
++#if defined(__VISUALDSPVERSION__)
++ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
++# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
++# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
++# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
++#endif
++
++#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
++# define COMPILER_ID "IAR"
++# if defined(__VER__) && defined(__ICCARM__)
++# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
++# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
++# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
++# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
++# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
++# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
++# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
++# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
++# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
++# endif
++
++
++/* These compilers are either not known or too old to define an
++ identification macro. Try to identify the platform and guess that
++ it is the native compiler. */
++#elif defined(__hpux) || defined(__hpua)
++# define COMPILER_ID "HP"
++
++#else /* unknown compiler */
++# define COMPILER_ID ""
++#endif
++
++/* Construct the string literal in pieces to prevent the source from
++ getting matched. Store it in a pointer rather than an array
++ because some compilers will just produce instructions to fill the
++ array rather than assigning a pointer to a static array. */
++char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
++#ifdef SIMULATE_ID
++char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
++#endif
++
++#ifdef __QNXNTO__
++char const* qnxnto = "INFO" ":" "qnxnto[]";
++#endif
++
++#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
++char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
++#endif
++
++#define STRINGIFY_HELPER(X) #X
++#define STRINGIFY(X) STRINGIFY_HELPER(X)
++
++/* Identify known platforms by name. */
++#if defined(__linux) || defined(__linux__) || defined(linux)
++# define PLATFORM_ID "Linux"
++
++#elif defined(__MSYS__)
++# define PLATFORM_ID "MSYS"
++
++#elif defined(__CYGWIN__)
++# define PLATFORM_ID "Cygwin"
++
++#elif defined(__MINGW32__)
++# define PLATFORM_ID "MinGW"
++
++#elif defined(__APPLE__)
++# define PLATFORM_ID "Darwin"
++
++#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
++# define PLATFORM_ID "Windows"
++
++#elif defined(__FreeBSD__) || defined(__FreeBSD)
++# define PLATFORM_ID "FreeBSD"
++
++#elif defined(__NetBSD__) || defined(__NetBSD)
++# define PLATFORM_ID "NetBSD"
++
++#elif defined(__OpenBSD__) || defined(__OPENBSD)
++# define PLATFORM_ID "OpenBSD"
++
++#elif defined(__sun) || defined(sun)
++# define PLATFORM_ID "SunOS"
++
++#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
++# define PLATFORM_ID "AIX"
++
++#elif defined(__hpux) || defined(__hpux__)
++# define PLATFORM_ID "HP-UX"
++
++#elif defined(__HAIKU__)
++# define PLATFORM_ID "Haiku"
++
++#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
++# define PLATFORM_ID "BeOS"
++
++#elif defined(__QNX__) || defined(__QNXNTO__)
++# define PLATFORM_ID "QNX"
++
++#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
++# define PLATFORM_ID "Tru64"
++
++#elif defined(__riscos) || defined(__riscos__)
++# define PLATFORM_ID "RISCos"
++
++#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
++# define PLATFORM_ID "SINIX"
++
++#elif defined(__UNIX_SV__)
++# define PLATFORM_ID "UNIX_SV"
++
++#elif defined(__bsdos__)
++# define PLATFORM_ID "BSDOS"
++
++#elif defined(_MPRAS) || defined(MPRAS)
++# define PLATFORM_ID "MP-RAS"
++
++#elif defined(__osf) || defined(__osf__)
++# define PLATFORM_ID "OSF1"
++
++#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
++# define PLATFORM_ID "SCO_SV"
++
++#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
++# define PLATFORM_ID "ULTRIX"
++
++#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
++# define PLATFORM_ID "Xenix"
++
++#elif defined(__WATCOMC__)
++# if defined(__LINUX__)
++# define PLATFORM_ID "Linux"
++
++# elif defined(__DOS__)
++# define PLATFORM_ID "DOS"
++
++# elif defined(__OS2__)
++# define PLATFORM_ID "OS2"
++
++# elif defined(__WINDOWS__)
++# define PLATFORM_ID "Windows3x"
++
++# elif defined(__VXWORKS__)
++# define PLATFORM_ID "VxWorks"
++
++# else /* unknown platform */
++# define PLATFORM_ID
++# endif
++
++#elif defined(__INTEGRITY)
++# if defined(INT_178B)
++# define PLATFORM_ID "Integrity178"
++
++# else /* regular Integrity */
++# define PLATFORM_ID "Integrity"
++# endif
++
++#else /* unknown platform */
++# define PLATFORM_ID
++
++#endif
++
++/* For windows compilers MSVC and Intel we can determine
++ the architecture of the compiler being used. This is because
++ the compilers do not have flags that can change the architecture,
++ but rather depend on which compiler is being used
++*/
++#if defined(_WIN32) && defined(_MSC_VER)
++# if defined(_M_IA64)
++# define ARCHITECTURE_ID "IA64"
++
++# elif defined(_M_ARM64EC)
++# define ARCHITECTURE_ID "ARM64EC"
++
++# elif defined(_M_X64) || defined(_M_AMD64)
++# define ARCHITECTURE_ID "x64"
++
++# elif defined(_M_IX86)
++# define ARCHITECTURE_ID "X86"
++
++# elif defined(_M_ARM64)
++# define ARCHITECTURE_ID "ARM64"
++
++# elif defined(_M_ARM)
++# if _M_ARM == 4
++# define ARCHITECTURE_ID "ARMV4I"
++# elif _M_ARM == 5
++# define ARCHITECTURE_ID "ARMV5I"
++# else
++# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
++# endif
++
++# elif defined(_M_MIPS)
++# define ARCHITECTURE_ID "MIPS"
++
++# elif defined(_M_SH)
++# define ARCHITECTURE_ID "SHx"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__WATCOMC__)
++# if defined(_M_I86)
++# define ARCHITECTURE_ID "I86"
++
++# elif defined(_M_IX86)
++# define ARCHITECTURE_ID "X86"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
++# if defined(__ICCARM__)
++# define ARCHITECTURE_ID "ARM"
++
++# elif defined(__ICCRX__)
++# define ARCHITECTURE_ID "RX"
++
++# elif defined(__ICCRH850__)
++# define ARCHITECTURE_ID "RH850"
++
++# elif defined(__ICCRL78__)
++# define ARCHITECTURE_ID "RL78"
++
++# elif defined(__ICCRISCV__)
++# define ARCHITECTURE_ID "RISCV"
++
++# elif defined(__ICCAVR__)
++# define ARCHITECTURE_ID "AVR"
++
++# elif defined(__ICC430__)
++# define ARCHITECTURE_ID "MSP430"
++
++# elif defined(__ICCV850__)
++# define ARCHITECTURE_ID "V850"
++
++# elif defined(__ICC8051__)
++# define ARCHITECTURE_ID "8051"
++
++# elif defined(__ICCSTM8__)
++# define ARCHITECTURE_ID "STM8"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__ghs__)
++# if defined(__PPC64__)
++# define ARCHITECTURE_ID "PPC64"
++
++# elif defined(__ppc__)
++# define ARCHITECTURE_ID "PPC"
++
++# elif defined(__ARM__)
++# define ARCHITECTURE_ID "ARM"
++
++# elif defined(__x86_64__)
++# define ARCHITECTURE_ID "x64"
++
++# elif defined(__i386__)
++# define ARCHITECTURE_ID "X86"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#elif defined(__TI_COMPILER_VERSION__)
++# if defined(__TI_ARM__)
++# define ARCHITECTURE_ID "ARM"
++
++# elif defined(__MSP430__)
++# define ARCHITECTURE_ID "MSP430"
++
++# elif defined(__TMS320C28XX__)
++# define ARCHITECTURE_ID "TMS320C28x"
++
++# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
++# define ARCHITECTURE_ID "TMS320C6x"
++
++# else /* unknown architecture */
++# define ARCHITECTURE_ID ""
++# endif
++
++#else
++# define ARCHITECTURE_ID
++#endif
++
++/* Convert integer to decimal digit literals. */
++#define DEC(n) \
++ ('0' + (((n) / 10000000)%10)), \
++ ('0' + (((n) / 1000000)%10)), \
++ ('0' + (((n) / 100000)%10)), \
++ ('0' + (((n) / 10000)%10)), \
++ ('0' + (((n) / 1000)%10)), \
++ ('0' + (((n) / 100)%10)), \
++ ('0' + (((n) / 10)%10)), \
++ ('0' + ((n) % 10))
++
++/* Convert integer to hex digit literals. */
++#define HEX(n) \
++ ('0' + ((n)>>28 & 0xF)), \
++ ('0' + ((n)>>24 & 0xF)), \
++ ('0' + ((n)>>20 & 0xF)), \
++ ('0' + ((n)>>16 & 0xF)), \
++ ('0' + ((n)>>12 & 0xF)), \
++ ('0' + ((n)>>8 & 0xF)), \
++ ('0' + ((n)>>4 & 0xF)), \
++ ('0' + ((n) & 0xF))
++
++/* Construct a string literal encoding the version number. */
++#ifdef COMPILER_VERSION
++char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
++
++/* Construct a string literal encoding the version number components. */
++#elif defined(COMPILER_VERSION_MAJOR)
++char const info_version[] = {
++ 'I', 'N', 'F', 'O', ':',
++ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
++ COMPILER_VERSION_MAJOR,
++# ifdef COMPILER_VERSION_MINOR
++ '.', COMPILER_VERSION_MINOR,
++# ifdef COMPILER_VERSION_PATCH
++ '.', COMPILER_VERSION_PATCH,
++# ifdef COMPILER_VERSION_TWEAK
++ '.', COMPILER_VERSION_TWEAK,
++# endif
++# endif
++# endif
++ ']','\0'};
++#endif
++
++/* Construct a string literal encoding the internal version number. */
++#ifdef COMPILER_VERSION_INTERNAL
++char const info_version_internal[] = {
++ 'I', 'N', 'F', 'O', ':',
++ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
++ 'i','n','t','e','r','n','a','l','[',
++ COMPILER_VERSION_INTERNAL,']','\0'};
++#elif defined(COMPILER_VERSION_INTERNAL_STR)
++char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
++#endif
++
++/* Construct a string literal encoding the version number components. */
++#ifdef SIMULATE_VERSION_MAJOR
++char const info_simulate_version[] = {
++ 'I', 'N', 'F', 'O', ':',
++ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
++ SIMULATE_VERSION_MAJOR,
++# ifdef SIMULATE_VERSION_MINOR
++ '.', SIMULATE_VERSION_MINOR,
++# ifdef SIMULATE_VERSION_PATCH
++ '.', SIMULATE_VERSION_PATCH,
++# ifdef SIMULATE_VERSION_TWEAK
++ '.', SIMULATE_VERSION_TWEAK,
++# endif
++# endif
++# endif
++ ']','\0'};
++#endif
++
++/* Construct the string literal in pieces to prevent the source from
++ getting matched. Store it in a pointer rather than an array
++ because some compilers will just produce instructions to fill the
++ array rather than assigning a pointer to a static array. */
++char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
++char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
++
++
++
++#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
++# if defined(__INTEL_CXX11_MODE__)
++# if defined(__cpp_aggregate_nsdmi)
++# define CXX_STD 201402L
++# else
++# define CXX_STD 201103L
++# endif
++# else
++# define CXX_STD 199711L
++# endif
++#elif defined(_MSC_VER) && defined(_MSVC_LANG)
++# define CXX_STD _MSVC_LANG
++#else
++# define CXX_STD __cplusplus
++#endif
++
++const char* info_language_standard_default = "INFO" ":" "standard_default["
++#if CXX_STD > 202002L
++ "23"
++#elif CXX_STD > 201703L
++ "20"
++#elif CXX_STD >= 201703L
++ "17"
++#elif CXX_STD >= 201402L
++ "14"
++#elif CXX_STD >= 201103L
++ "11"
++#else
++ "98"
++#endif
++"]";
++
++const char* info_language_extensions_default = "INFO" ":" "extensions_default["
++/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */
++#if (defined(__clang__) || defined(__GNUC__) || \
++ defined(__TI_COMPILER_VERSION__)) && \
++ !defined(__STRICT_ANSI__) && !defined(_MSC_VER)
++ "ON"
++#else
++ "OFF"
++#endif
++"]";
++
++/*--------------------------------------------------------------------------*/
++
++int main(int argc, char* argv[])
++{
++ int require = 0;
++ require += info_compiler[argc];
++ require += info_platform[argc];
++#ifdef COMPILER_VERSION_MAJOR
++ require += info_version[argc];
++#endif
++#ifdef COMPILER_VERSION_INTERNAL
++ require += info_version_internal[argc];
++#endif
++#ifdef SIMULATE_ID
++ require += info_simulate[argc];
++#endif
++#ifdef SIMULATE_VERSION_MAJOR
++ require += info_simulate_version[argc];
++#endif
++#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
++ require += info_cray[argc];
++#endif
++ require += info_language_standard_default[argc];
++ require += info_language_extensions_default[argc];
++ (void)argv;
++ return require;
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o
+new file mode 100644
+index 0000000..61f3d99
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeError.log b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeError.log
+new file mode 100644
+index 0000000..088c1a6
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeError.log
+@@ -0,0 +1,5 @@
++Checking whether the ASM compiler is GNU using "--version" did not match "(GNU assembler)|(GCC)|(Free Software Foundation)":
++Android (12470979, +pgo, -bolt, +lto, -mlgo, based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
++Target: x86_64-apple-darwin24.3.0
++Thread model: posix
++InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeOutput.log b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeOutput.log
+new file mode 100644
+index 0000000..68e7751
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeOutput.log
+@@ -0,0 +1,267 @@
++The target system is: Android - 1 - aarch64
++The host system is: Darwin - 24.3.0 - arm64
++Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded.
++Compiler: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang
++Build flags: -g;-DANDROID;-fdata-sections;-ffunction-sections;-funwind-tables;-fstack-protector-strong;-no-canonical-prefixes;-D_FORTIFY_SOURCE=2;-Wformat;-Werror=format-security;
++Id flags: -c;--target=aarch64-none-linux-android24
++
++The output was:
++0
++
++
++Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.o"
++
++The C compiler identification is Clang, found in "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o"
++
++Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
++Compiler: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++
++Build flags: -g;-DANDROID;-fdata-sections;-ffunction-sections;-funwind-tables;-fstack-protector-strong;-no-canonical-prefixes;-D_FORTIFY_SOURCE=2;-Wformat;-Werror=format-security;;-O3;-frtti;-fexceptions;-Wall;-fstack-protector-all
++Id flags: -c;--target=aarch64-none-linux-android24
++
++The output was:
++0
++
++
++Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CMakeCXXCompilerId.o"
++
++The CXX compiler identification is Clang, found in "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdCXX/CMakeCXXCompilerId.o"
++
++Detecting C compiler ABI info compiled with the following output:
++Change Dir: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp
++
++Run Build Command(s):/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja cmTC_5018b && [1/2] Building C object CMakeFiles/cmTC_5018b.dir/CMakeCCompilerABI.c.o
++Android (12470979, +pgo, -bolt, +lto, -mlgo, based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
++Target: aarch64-none-linux-android24
++Thread model: posix
++InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin
++ (in-process)
++ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang" -cc1 -triple aarch64-none-linux-android24 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -resource-dir /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_045bc.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_045bc.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fno-signed-char -fgnuc-version=4.2.1 -fcolor-diagnostics -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_045bc.dir/CMakeCCompilerABI.c.o -x c /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c
++clang -cc1 version 18.0.3 based upon LLVM 18.0.3 default target x86_64-apple-darwin24.3.0
++ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include"
++ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include"
++#include "..." search starts here:
++#include <...> search starts here:
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include
++End of search list.
++[2/2] Linking C executable cmTC_5018b
++Android (12470979, +pgo, -bolt, +lto, -mlgo, based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
++Target: aarch64-none-linux-android24
++Thread model: posix
++InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin
++ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o cmTC_5018b /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_5018b.dir/CMakeCCompilerABI.c.o /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o
++
++
++
++Parsed C implicit include dir info from above output: rv=done
++ found start of include info
++ found start of implicit include info
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include]
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android]
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++ end of search list found
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include]
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android]
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++ implicit include dirs: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++
++
++Parsed C implicit link information from above output:
++ link line regex: [^( *|.*[/\])(ld\.lld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
++ ignore line: [Change Dir: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp]
++ ignore line: []
++ ignore line: [Run Build Command(s):/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja cmTC_5018b && [1/2] Building C object CMakeFiles/cmTC_5018b.dir/CMakeCCompilerABI.c.o]
++ ignore line: [Android (12470979 +pgo -bolt +lto -mlgo based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)]
++ ignore line: [Target: aarch64-none-linux-android24]
++ ignore line: [Thread model: posix]
++ ignore line: [InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin]
++ ignore line: [ (in-process)]
++ ignore line: [ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang" -cc1 -triple aarch64-none-linux-android24 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -resource-dir /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_045bc.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_045bc.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fno-signed-char -fgnuc-version=4.2.1 -fcolor-diagnostics -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_045bc.dir/CMakeCCompilerABI.c.o -x c /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c]
++ ignore line: [clang -cc1 version 18.0.3 based upon LLVM 18.0.3 default target x86_64-apple-darwin24.3.0]
++ ignore line: [ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include"]
++ ignore line: [ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include"]
++ ignore line: [#include "..." search starts here:]
++ ignore line: [#include <...> search starts here:]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++ ignore line: [End of search list.]
++ ignore line: [[2/2] Linking C executable cmTC_5018b]
++ ignore line: [Android (12470979 +pgo -bolt +lto -mlgo based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)]
++ ignore line: [Target: aarch64-none-linux-android24]
++ ignore line: [Thread model: posix]
++ ignore line: [InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin]
++ link line: [ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o cmTC_5018b /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_5018b.dir/CMakeCCompilerABI.c.o /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld] ==> ignore
++ arg [--sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot] ==> ignore
++ arg [-EL] ==> ignore
++ arg [--fix-cortex-a53-843419] ==> ignore
++ arg [-znow] ==> ignore
++ arg [-zrelro] ==> ignore
++ arg [-zmax-page-size=4096] ==> ignore
++ arg [--hash-style=gnu] ==> ignore
++ arg [--eh-frame-hdr] ==> ignore
++ arg [-m] ==> ignore
++ arg [aarch64linux] ==> ignore
++ arg [-pie] ==> ignore
++ arg [-dynamic-linker] ==> ignore
++ arg [/system/bin/linker64] ==> ignore
++ arg [-o] ==> ignore
++ arg [cmTC_5018b] ==> ignore
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o] ==> obj [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib]
++ arg [--build-id=sha1] ==> ignore
++ arg [--no-rosegment] ==> ignore
++ arg [--no-undefined-version] ==> ignore
++ arg [--fatal-warnings] ==> ignore
++ arg [--no-undefined] ==> ignore
++ arg [CMakeFiles/cmTC_5018b.dir/CMakeCCompilerABI.c.o] ==> ignore
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] ==> lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ arg [-l:libunwind.a] ==> lib [-l:libunwind.a]
++ arg [-ldl] ==> lib [dl]
++ arg [-lc] ==> lib [c]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] ==> lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ arg [-l:libunwind.a] ==> lib [-l:libunwind.a]
++ arg [-ldl] ==> lib [dl]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o] ==> obj [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o]
++ remove lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ remove lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib]
++ implicit libs: [-l:libunwind.a;dl;c;-l:libunwind.a;dl]
++ implicit objs: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o]
++ implicit dirs: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib]
++ implicit fwks: []
++
++
++Detecting CXX compiler ABI info compiled with the following output:
++Change Dir: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp
++
++Run Build Command(s):/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja cmTC_5c510 && [1/2] Building CXX object CMakeFiles/cmTC_5c510.dir/CMakeCXXCompilerABI.cpp.o
++Android (12470979, +pgo, -bolt, +lto, -mlgo, based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
++Target: aarch64-none-linux-android24
++Thread model: posix
++InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin
++ (in-process)
++ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++" -cc1 -triple aarch64-none-linux-android24 -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCXXCompilerABI.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -resource-dir /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_a9293.dir/CMakeCXXCompilerABI.cpp.o.d -MT CMakeFiles/cmTC_a9293.dir/CMakeCXXCompilerABI.cpp.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1 -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include -O3 -Wformat -Wall -fdeprecated-macro -ferror-limit 19 -femulated-tls -stack-protector 3 -fno-signed-char -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_a9293.dir/CMakeCXXCompilerABI.cpp.o -x c++ /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp
++clang -cc1 version 18.0.3 based upon LLVM 18.0.3 default target x86_64-apple-darwin24.3.0
++ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include"
++ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include"
++#include "..." search starts here:
++#include <...> search starts here:
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android
++ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include
++End of search list.
++[2/2] Linking CXX executable cmTC_5c510
++Android (12470979, +pgo, -bolt, +lto, -mlgo, based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
++Target: aarch64-none-linux-android24
++Thread model: posix
++InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin
++ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o cmTC_5c510 /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_5c510.dir/CMakeCXXCompilerABI.cpp.o -lc++ -lm /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o
++
++
++
++Parsed CXX implicit include dir info from above output: rv=done
++ found start of include info
++ found start of implicit include info
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1]
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include]
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android]
++ add: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++ end of search list found
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1]
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include]
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android]
++ collapse include dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++ implicit include dirs: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++
++
++Parsed CXX implicit link information from above output:
++ link line regex: [^( *|.*[/\])(ld\.lld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)]
++ ignore line: [Change Dir: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp]
++ ignore line: []
++ ignore line: [Run Build Command(s):/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja cmTC_5c510 && [1/2] Building CXX object CMakeFiles/cmTC_5c510.dir/CMakeCXXCompilerABI.cpp.o]
++ ignore line: [Android (12470979 +pgo -bolt +lto -mlgo based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)]
++ ignore line: [Target: aarch64-none-linux-android24]
++ ignore line: [Thread model: posix]
++ ignore line: [InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin]
++ ignore line: [ (in-process)]
++ ignore line: [ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++" -cc1 -triple aarch64-none-linux-android24 -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCXXCompilerABI.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/CMakeTmp -resource-dir /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_a9293.dir/CMakeCXXCompilerABI.cpp.o.d -MT CMakeFiles/cmTC_a9293.dir/CMakeCXXCompilerABI.cpp.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1 -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include -internal-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include -internal-externc-isystem /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include -O3 -Wformat -Wall -fdeprecated-macro -ferror-limit 19 -femulated-tls -stack-protector 3 -fno-signed-char -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_a9293.dir/CMakeCXXCompilerABI.cpp.o -x c++ /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp]
++ ignore line: [clang -cc1 version 18.0.3 based upon LLVM 18.0.3 default target x86_64-apple-darwin24.3.0]
++ ignore line: [ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/local/include"]
++ ignore line: [ignoring nonexistent directory "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/include"]
++ ignore line: [#include "..." search starts here:]
++ ignore line: [#include <...> search starts here:]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/c++/v1]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/include]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/aarch64-linux-android]
++ ignore line: [ /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include]
++ ignore line: [End of search list.]
++ ignore line: [[2/2] Linking CXX executable cmTC_5c510]
++ ignore line: [Android (12470979 +pgo -bolt +lto -mlgo based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)]
++ ignore line: [Target: aarch64-none-linux-android24]
++ ignore line: [Thread model: posix]
++ ignore line: [InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin]
++ link line: [ "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld" --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o cmTC_5c510 /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24 -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android -L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_5c510.dir/CMakeCXXCompilerABI.cpp.o -lc++ -lm /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld] ==> ignore
++ arg [--sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot] ==> ignore
++ arg [-EL] ==> ignore
++ arg [--fix-cortex-a53-843419] ==> ignore
++ arg [-znow] ==> ignore
++ arg [-zrelro] ==> ignore
++ arg [-zmax-page-size=4096] ==> ignore
++ arg [--hash-style=gnu] ==> ignore
++ arg [--eh-frame-hdr] ==> ignore
++ arg [-m] ==> ignore
++ arg [aarch64linux] ==> ignore
++ arg [-pie] ==> ignore
++ arg [-dynamic-linker] ==> ignore
++ arg [/system/bin/linker64] ==> ignore
++ arg [-o] ==> ignore
++ arg [cmTC_5c510] ==> ignore
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o] ==> obj [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android]
++ arg [-L/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib] ==> dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib]
++ arg [--build-id=sha1] ==> ignore
++ arg [--no-rosegment] ==> ignore
++ arg [--no-undefined-version] ==> ignore
++ arg [--fatal-warnings] ==> ignore
++ arg [--no-undefined] ==> ignore
++ arg [CMakeFiles/cmTC_5c510.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
++ arg [-lc++] ==> lib [c++]
++ arg [-lm] ==> lib [m]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] ==> lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ arg [-l:libunwind.a] ==> lib [-l:libunwind.a]
++ arg [-ldl] ==> lib [dl]
++ arg [-lc] ==> lib [c]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] ==> lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ arg [-l:libunwind.a] ==> lib [-l:libunwind.a]
++ arg [-ldl] ==> lib [dl]
++ arg [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o] ==> obj [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o]
++ remove lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ remove lib [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android]
++ collapse library dir [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib] ==> [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib]
++ implicit libs: [c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl]
++ implicit objs: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtbegin_dynamic.o;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/crtend_android.o]
++ implicit dirs: [/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/18/lib/linux/aarch64;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android;/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib]
++ implicit fwks: []
++
++
++Checking whether the ASM compiler is Clang using "--version" matched "(clang version)":
++Android (12470979, +pgo, -bolt, +lto, -mlgo, based on r522817c) clang version 18.0.3 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)
++Target: x86_64-apple-darwin24.3.0
++Thread model: posix
++InstalledDir: /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/TargetDirectories.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/TargetDirectories.txt
+new file mode 100644
+index 0000000..d9d47d2
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/TargetDirectories.txt
+@@ -0,0 +1,6 @@
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rnmmkv.dir
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/edit_cache.dir
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rebuild_cache.dir
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/edit_cache.dir
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/rebuild_cache.dir
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/cmake.check_cache b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/cmake.check_cache
+new file mode 100644
+index 0000000..3dccd73
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/cmake.check_cache
+@@ -0,0 +1 @@
++# This file is generated by cmake for dependency checking of the CMakeCache.txt file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o
+new file mode 100644
+index 0000000..2ce9ab1
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rules.ninja b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rules.ninja
+new file mode 100644
+index 0000000..e06f79e
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/CMakeFiles/rules.ninja
+@@ -0,0 +1,93 @@
++# CMAKE generated file: DO NOT EDIT!
++# Generated by "Ninja" Generator, CMake Version 3.22
++
++# This file contains all the rules used to get the outputs files
++# built from the input files.
++# It is included in the main 'build.ninja'.
++
++# =============================================================================
++# Project: PACKAGE_NAME
++# Configurations: Debug
++# =============================================================================
++# =============================================================================
++
++#############################################
++# Rule for compiling CXX files.
++
++rule CXX_COMPILER__rnmmkv_Debug
++ depfile = $DEP_FILE
++ deps = gcc
++ command = ccache /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in
++ description = Building CXX object $out
++
++
++#############################################
++# Rule for linking CXX shared library.
++
++rule CXX_SHARED_LIBRARY_LINKER__rnmmkv_Debug
++ command = $PRE_LINK && /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -fPIC $LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS $LINK_FLAGS -shared $SONAME_FLAG$SONAME -o $TARGET_FILE $in $LINK_PATH $LINK_LIBRARIES && $POST_BUILD
++ description = Linking CXX shared library $TARGET_FILE
++ restat = $RESTAT
++
++
++#############################################
++# Rule for running custom commands.
++
++rule CUSTOM_COMMAND
++ command = $COMMAND
++ description = $DESC
++
++
++#############################################
++# Rule for compiling ASM files.
++
++rule ASM_COMPILER__core_Debug
++ depfile = $DEP_FILE
++ deps = gcc
++ command = /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in
++ description = Building ASM object $out
++
++
++#############################################
++# Rule for compiling CXX files.
++
++rule CXX_COMPILER__core_Debug
++ depfile = $DEP_FILE
++ deps = gcc
++ command = ccache /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in
++ description = Building CXX object $out
++
++
++#############################################
++# Rule for linking CXX static library.
++
++rule CXX_STATIC_LIBRARY_LINKER__core_Debug
++ command = $PRE_LINK && /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake -E rm -f $TARGET_FILE && /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar qc $TARGET_FILE $LINK_FLAGS $in && /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ranlib $TARGET_FILE && /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake -E touch $TARGET_FILE && $POST_BUILD
++ description = Linking CXX static library $TARGET_FILE
++ restat = $RESTAT
++
++
++#############################################
++# Rule for re-running cmake.
++
++rule RERUN_CMAKE
++ command = /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv -B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++ description = Re-running CMake...
++ generator = 1
++
++
++#############################################
++# Rule for cleaning all built files.
++
++rule CLEAN
++ command = /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS
++ description = Cleaning all built files...
++
++
++#############################################
++# Rule for printing all primary targets available.
++
++rule HELP
++ command = /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja -t targets
++ description = All primary targets available:
++
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/additional_project_files.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/additional_project_files.txt
+new file mode 100644
+index 0000000..f0e585a
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/additional_project_files.txt
+@@ -0,0 +1,29 @@
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVMetaInfo.hpp
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_locl.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_opensslconf.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_locl.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md32_common.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_arm_arch.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/Checksum.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/zconf.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/zutil.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVPredef.h
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build.json
+new file mode 100644
+index 0000000..12c81e7
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build.json
+@@ -0,0 +1,49 @@
++{
++ "buildFiles": [
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt",
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt"
++ ],
++ "cleanCommandsComponents": [
++ [
++ "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja",
++ "-C",
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "clean"
++ ]
++ ],
++ "buildTargetsCommandComponents": [
++ "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja",
++ "-C",
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "{LIST_OF_TARGETS_TO_BUILD}"
++ ],
++ "libraries": {
++ "core::@57760688d1f824db5d9c": {
++ "toolchain": "toolchain",
++ "abi": "arm64-v8a",
++ "artifactName": "core",
++ "output": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/libcore.a"
++ },
++ "rnmmkv::@6890427a1f51a3e7e1df": {
++ "toolchain": "toolchain",
++ "abi": "arm64-v8a",
++ "artifactName": "rnmmkv",
++ "output": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so",
++ "runtimeFiles": [
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.arm64-v8a/libfbjni.so",
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/libs/android.arm64-v8a/libjsi.so",
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/libs/android.arm64-v8a/libreactnative.so"
++ ]
++ }
++ },
++ "toolchains": {
++ "toolchain": {
++ "cCompilerExecutable": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang.lld",
++ "cppCompilerExecutable": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++.lld"
++ }
++ },
++ "cFileExtensions": [],
++ "cppFileExtensions": [
++ "cpp"
++ ]
++}
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build_mini.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build_mini.json
+new file mode 100644
+index 0000000..27c81fa
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build_mini.json
+@@ -0,0 +1,38 @@
++{
++ "buildFiles": [
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt",
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt"
++ ],
++ "cleanCommandsComponents": [
++ [
++ "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja",
++ "-C",
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "clean"
++ ]
++ ],
++ "buildTargetsCommandComponents": [
++ "/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja",
++ "-C",
++ "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "{LIST_OF_TARGETS_TO_BUILD}"
++ ],
++ "libraries": {
++ "core::@57760688d1f824db5d9c": {
++ "artifactName": "core",
++ "abi": "arm64-v8a",
++ "output": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/libcore.a",
++ "runtimeFiles": []
++ },
++ "rnmmkv::@6890427a1f51a3e7e1df": {
++ "artifactName": "rnmmkv",
++ "abi": "arm64-v8a",
++ "output": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so",
++ "runtimeFiles": [
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.arm64-v8a/libfbjni.so",
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/libs/android.arm64-v8a/libjsi.so",
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/libs/android.arm64-v8a/libreactnative.so"
++ ]
++ }
++ }
++}
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build.ninja b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build.ninja
+new file mode 100644
+index 0000000..47a9641
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build.ninja
+@@ -0,0 +1,537 @@
++# CMAKE generated file: DO NOT EDIT!
++# Generated by "Ninja" Generator, CMake Version 3.22
++
++# This file contains all the build statements describing the
++# compilation DAG.
++
++# =============================================================================
++# Write statements declared in CMakeLists.txt:
++#
++# Which is the root file.
++# =============================================================================
++
++# =============================================================================
++# Project: PACKAGE_NAME
++# Configurations: Debug
++# =============================================================================
++
++#############################################
++# Minimal version of Ninja required by this file
++
++ninja_required_version = 1.5
++
++
++#############################################
++# Set configuration variable for custom commands.
++
++CONFIGURATION = Debug
++# =============================================================================
++# Include auxiliary files.
++
++
++#############################################
++# Include rules file.
++
++include CMakeFiles/rules.ninja
++
++# =============================================================================
++
++#############################################
++# Logical path to working directory; prefix for absolute paths.
++
++cmake_ninja_workdir = /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/
++# =============================================================================
++# Object build statements for SHARED_LIBRARY target rnmmkv
++
++
++#############################################
++# Order-only phony target for rnmmkv
++
++build cmake_object_order_depends_target_rnmmkv: phony || cmake_object_order_depends_target_core
++
++build CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o: CXX_COMPILER__rnmmkv_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/rnmmkv-adapter.cpp || cmake_object_order_depends_target_rnmmkv
++ DEFINES = -Drnmmkv_EXPORTS
++ DEP_FILE = CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/include -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/include -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/include
++ OBJECT_DIR = CMakeFiles/rnmmkv.dir
++ OBJECT_FILE_DIR = CMakeFiles/rnmmkv.dir
++ TARGET_COMPILE_PDB = CMakeFiles/rnmmkv.dir/
++ TARGET_PDB = /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.pdb
++
++
++# =============================================================================
++# Link build statements for SHARED_LIBRARY target rnmmkv
++
++
++#############################################
++# Link the shared library /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so
++
++build /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so: CXX_SHARED_LIBRARY_LINKER__rnmmkv_Debug CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o | core/libcore.a /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so /Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.arm64-v8a/libfbjni.so /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/libs/android.arm64-v8a/libjsi.so /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/libs/android.arm64-v8a/libreactnative.so /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so || core/libcore.a
++ LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info
++ LINK_FLAGS = -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments
++ LINK_LIBRARIES = core/libcore.a /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/liblog.so /Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.arm64-v8a/libfbjni.so /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/libs/android.arm64-v8a/libjsi.so /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/libs/android.arm64-v8a/libreactnative.so -landroid /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/24/libz.so -latomic -lm
++ OBJECT_DIR = CMakeFiles/rnmmkv.dir
++ POST_BUILD = :
++ PRE_LINK = :
++ SONAME = librnmmkv.so
++ SONAME_FLAG = -Wl,-soname,
++ TARGET_COMPILE_PDB = CMakeFiles/rnmmkv.dir/
++ TARGET_FILE = /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so
++ TARGET_PDB = /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.pdb
++
++
++#############################################
++# Utility command for edit_cache
++
++build CMakeFiles/edit_cache.util: CUSTOM_COMMAND
++ COMMAND = cd /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a && /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv -B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++ DESC = Running CMake cache editor...
++ pool = console
++ restat = 1
++
++build edit_cache: phony CMakeFiles/edit_cache.util
++
++
++#############################################
++# Utility command for rebuild_cache
++
++build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND
++ COMMAND = cd /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a && /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv -B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++ DESC = Running CMake to regenerate build system...
++ pool = console
++ restat = 1
++
++build rebuild_cache: phony CMakeFiles/rebuild_cache.util
++
++# =============================================================================
++# Write statements declared in CMakeLists.txt:
++# /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt
++# =============================================================================
++
++# =============================================================================
++# Object build statements for STATIC_LIBRARY target core
++
++
++#############################################
++# Order-only phony target for core
++
++build cmake_object_order_depends_target_core: phony || core/CMakeFiles/core.dir
++
++build core/CMakeFiles/core.dir/MMKV.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMKV.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MMKV_Android.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_Android.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMKV_Android.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MMKV_IO.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMKV_IO.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MMKV_OSX.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_OSX.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMKV_OSX.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MMKVLog.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMKVLog.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog_Android.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/CodedInputData.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/CodedInputData.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData_OSX.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt_OSX.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/CodedOutputData.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/CodedOutputData.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/KeyValueHolder.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/KeyValueHolder.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/PBUtility.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/PBUtility.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MiniPBCoder.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MiniPBCoder.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder_OSX.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MMBuffer.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MMBuffer.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/InterProcessLock.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/InterProcessLock.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Win32.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Android.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MemoryFile.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MemoryFile.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Android.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Linux.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Win32.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_OSX.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/ThreadLock.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/ThreadLock.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock_Win32.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_core.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes/openssl
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_cfb128.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes/openssl
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes/openssl
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_one.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes/openssl
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/crc32_armv8.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/crc32
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o: CXX_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.cpp || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o.d
++ FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/crc32/zlib
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o: ASM_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o.d
++ FLAGS = -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes/openssl
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++build core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o: ASM_COMPILER__core_Debug /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S || cmake_object_order_depends_target_core
++ DEP_FILE = core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o.d
++ FLAGS = -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC
++ INCLUDES = -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ OBJECT_FILE_DIR = core/CMakeFiles/core.dir/aes/openssl
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_PDB = core/libcore.pdb
++
++
++# =============================================================================
++# Link build statements for STATIC_LIBRARY target core
++
++
++#############################################
++# Link the static library core/libcore.a
++
++build core/libcore.a: CXX_STATIC_LIBRARY_LINKER__core_Debug core/CMakeFiles/core.dir/MMKV.cpp.o core/CMakeFiles/core.dir/MMKV_Android.cpp.o core/CMakeFiles/core.dir/MMKV_IO.cpp.o core/CMakeFiles/core.dir/MMKV_OSX.cpp.o core/CMakeFiles/core.dir/MMKVLog.cpp.o core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o core/CMakeFiles/core.dir/CodedInputData.cpp.o core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o core/CMakeFiles/core.dir/CodedOutputData.cpp.o core/CMakeFiles/core.dir/KeyValueHolder.cpp.o core/CMakeFiles/core.dir/PBUtility.cpp.o core/CMakeFiles/core.dir/MiniPBCoder.cpp.o core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o core/CMakeFiles/core.dir/MMBuffer.cpp.o core/CMakeFiles/core.dir/InterProcessLock.cpp.o core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o core/CMakeFiles/core.dir/MemoryFile.cpp.o core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o core/CMakeFiles/core.dir/ThreadLock.cpp.o core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o
++ LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info
++ OBJECT_DIR = core/CMakeFiles/core.dir
++ POST_BUILD = :
++ PRE_LINK = :
++ TARGET_COMPILE_PDB = core/CMakeFiles/core.dir/core.pdb
++ TARGET_FILE = core/libcore.a
++ TARGET_PDB = core/libcore.pdb
++
++
++#############################################
++# Utility command for edit_cache
++
++build core/CMakeFiles/edit_cache.util: CUSTOM_COMMAND
++ COMMAND = cd /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core && /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ccmake -S/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv -B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++ DESC = Running CMake cache editor...
++ pool = console
++ restat = 1
++
++build core/edit_cache: phony core/CMakeFiles/edit_cache.util
++
++
++#############################################
++# Utility command for rebuild_cache
++
++build core/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND
++ COMMAND = cd /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core && /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv -B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++ DESC = Running CMake to regenerate build system...
++ pool = console
++ restat = 1
++
++build core/rebuild_cache: phony core/CMakeFiles/rebuild_cache.util
++
++# =============================================================================
++# Target aliases.
++
++build core: phony core/libcore.a
++
++build libcore.a: phony core/libcore.a
++
++build librnmmkv.so: phony /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so
++
++build rnmmkv: phony /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so
++
++# =============================================================================
++# Folder targets.
++
++# =============================================================================
++
++#############################################
++# Folder: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++
++build all: phony /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a/librnmmkv.so core/all
++
++# =============================================================================
++
++#############################################
++# Folder: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core
++
++build core/all: phony core/libcore.a
++
++# =============================================================================
++# Built-in targets
++
++
++#############################################
++# Re-run CMake if any of its inputs changed.
++
++build build.ninja: RERUN_CMAKE | /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeASMCompiler.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeASMInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineASMCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestASMCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-ASM.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-ASM.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/abis.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android-legacy.toolchain.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/flags.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Clang.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Determine.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Initialize.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/platforms.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfig.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfigVersion.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeASMCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake
++ pool = console
++
++
++#############################################
++# A missing CMake input file is not an error.
++
++build /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeASMCompiler.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeASMInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineASMCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestASMCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-ASM.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-ASM.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/abis.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android-legacy.toolchain.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/flags.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Clang.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Determine.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Initialize.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Determine-Compiler.cmake /Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/platforms.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfig.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfigVersion.cmake /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeASMCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony
++
++
++#############################################
++# Clean all the built files.
++
++build clean: CLEAN
++
++
++#############################################
++# Print all primary targets available.
++
++build help: HELP
++
++
++#############################################
++# Make the all target the default.
++
++default all
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build_file_index.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build_file_index.txt
+new file mode 100644
+index 0000000..5c14b54
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build_file_index.txt
+@@ -0,0 +1,2 @@
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CMakeLists.txt
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/cmake_install.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/cmake_install.cmake
+new file mode 100644
+index 0000000..3d0c094
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/cmake_install.cmake
+@@ -0,0 +1,60 @@
++# Install script for directory: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv
++
++# Set the install prefix
++if(NOT DEFINED CMAKE_INSTALL_PREFIX)
++ set(CMAKE_INSTALL_PREFIX "/usr/local")
++endif()
++string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
++
++# Set the install configuration name.
++if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
++ if(BUILD_TYPE)
++ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
++ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
++ else()
++ set(CMAKE_INSTALL_CONFIG_NAME "Debug")
++ endif()
++ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
++endif()
++
++# Set the component getting installed.
++if(NOT CMAKE_INSTALL_COMPONENT)
++ if(COMPONENT)
++ message(STATUS "Install component: \"${COMPONENT}\"")
++ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
++ else()
++ set(CMAKE_INSTALL_COMPONENT)
++ endif()
++endif()
++
++# Install shared libraries without execute permission?
++if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
++ set(CMAKE_INSTALL_SO_NO_EXE "0")
++endif()
++
++# Is this installation the result of a crosscompile?
++if(NOT DEFINED CMAKE_CROSSCOMPILING)
++ set(CMAKE_CROSSCOMPILING "TRUE")
++endif()
++
++# Set default install directory permissions.
++if(NOT DEFINED CMAKE_OBJDUMP)
++ set(CMAKE_OBJDUMP "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump")
++endif()
++
++if(NOT CMAKE_INSTALL_LOCAL_ONLY)
++ # Include the install script for each subdirectory.
++ include("/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/cmake_install.cmake")
++
++endif()
++
++if(CMAKE_INSTALL_COMPONENT)
++ set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
++else()
++ set(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
++endif()
++
++string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
++ "${CMAKE_INSTALL_MANIFEST_FILES}")
++file(WRITE "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/${CMAKE_INSTALL_MANIFEST}"
++ "${CMAKE_INSTALL_MANIFEST_CONTENT}")
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json
+new file mode 100644
+index 0000000..5a5cceb
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json
+@@ -0,0 +1,182 @@
++[
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -Drnmmkv_EXPORTS -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/include -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/include -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/include -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -o CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/rnmmkv-adapter.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/rnmmkv-adapter.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV_IO.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKVLog.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputData.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedOutputData.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/KeyValueHolder.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/PBUtility.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MiniPBCoder.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMBuffer.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/InterProcessLock.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Win32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Win32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Linux.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Linux.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Win32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Win32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/ThreadLock.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock_Win32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock_Win32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_core.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_core.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_cfb128.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_cfb128.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_one.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_one.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/crc32_armv8.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/crc32_armv8.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC -o core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC -o core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S"
++}
++]
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json.bin b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json.bin
+new file mode 100644
+index 0000000..c649fe2
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json.bin differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/configure_fingerprint.bin b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/configure_fingerprint.bin
+new file mode 100644
+index 0000000..44ed276
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/configure_fingerprint.bin
+@@ -0,0 +1,28 @@
++C/C++ Structured Log
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/additional_project_files.txtC
++A
++?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint ָ2 ¸2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build.json ָ2 ø2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/android_gradle_build_mini.json ָ2 Ҹ2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build.ninja ָ2 2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build.ninja.txt ָ2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/build_file_index.txt ָ2 Ը2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json ָ2 2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/compile_commands.json.bin ָ2 E 2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/metadata_generation_command.txt ָ2
++ Ը2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/prefab_config.json ָ2 Ը2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/symbol_folder_index.txt ָ2 Ը2
++
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/CMakeLists.txt ָ2
2
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputData.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputData.cpp.o
+new file mode 100644
+index 0000000..cd9af89
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputData.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o
+new file mode 100644
+index 0000000..7d4c546
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o
+new file mode 100644
+index 0000000..51c9315
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o
+new file mode 100644
+index 0000000..bb8af37
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedOutputData.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedOutputData.cpp.o
+new file mode 100644
+index 0000000..d7a3ec2
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/CodedOutputData.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock.cpp.o
+new file mode 100644
+index 0000000..278e3db
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o
+new file mode 100644
+index 0000000..c2f6cb8
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o
+new file mode 100644
+index 0000000..351b861
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/KeyValueHolder.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/KeyValueHolder.cpp.o
+new file mode 100644
+index 0000000..ea92114
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/KeyValueHolder.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMBuffer.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMBuffer.cpp.o
+new file mode 100644
+index 0000000..9715703
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMBuffer.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV.cpp.o
+new file mode 100644
+index 0000000..2ef9163
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKVLog.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKVLog.cpp.o
+new file mode 100644
+index 0000000..e140232
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKVLog.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o
+new file mode 100644
+index 0000000..643578e
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_Android.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_Android.cpp.o
+new file mode 100644
+index 0000000..ad712d7
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_Android.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_IO.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_IO.cpp.o
+new file mode 100644
+index 0000000..0c0358b
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_IO.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_OSX.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_OSX.cpp.o
+new file mode 100644
+index 0000000..5fe6be9
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MMKV_OSX.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile.cpp.o
+new file mode 100644
+index 0000000..23c4c7a
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o
+new file mode 100644
+index 0000000..1b53ad7
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o
+new file mode 100644
+index 0000000..a9d4807
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o
+new file mode 100644
+index 0000000..532bc9c
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o
+new file mode 100644
+index 0000000..3871cd4
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MiniPBCoder.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MiniPBCoder.cpp.o
+new file mode 100644
+index 0000000..e70d9c8
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MiniPBCoder.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o
+new file mode 100644
+index 0000000..4424c14
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/PBUtility.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/PBUtility.cpp.o
+new file mode 100644
+index 0000000..bb4af51
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/PBUtility.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/ThreadLock.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/ThreadLock.cpp.o
+new file mode 100644
+index 0000000..d8b867b
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/ThreadLock.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o
+new file mode 100644
+index 0000000..77f6058
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o
+new file mode 100644
+index 0000000..0f08a15
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o
+new file mode 100644
+index 0000000..d7e0afc
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o
+new file mode 100644
+index 0000000..d6bd8f1
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o
+new file mode 100644
+index 0000000..026839c
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o
+new file mode 100644
+index 0000000..5cc8950
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o
+new file mode 100644
+index 0000000..3fd0206
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o
+new file mode 100644
+index 0000000..eb237ec
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o
+new file mode 100644
+index 0000000..f71d457
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o
+new file mode 100644
+index 0000000..d39ab97
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/cmake_install.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/cmake_install.cmake
+new file mode 100644
+index 0000000..90777b2
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/cmake_install.cmake
+@@ -0,0 +1,44 @@
++# Install script for directory: /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core
++
++# Set the install prefix
++if(NOT DEFINED CMAKE_INSTALL_PREFIX)
++ set(CMAKE_INSTALL_PREFIX "/usr/local")
++endif()
++string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
++
++# Set the install configuration name.
++if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
++ if(BUILD_TYPE)
++ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
++ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
++ else()
++ set(CMAKE_INSTALL_CONFIG_NAME "Debug")
++ endif()
++ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
++endif()
++
++# Set the component getting installed.
++if(NOT CMAKE_INSTALL_COMPONENT)
++ if(COMPONENT)
++ message(STATUS "Install component: \"${COMPONENT}\"")
++ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
++ else()
++ set(CMAKE_INSTALL_COMPONENT)
++ endif()
++endif()
++
++# Install shared libraries without execute permission?
++if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
++ set(CMAKE_INSTALL_SO_NO_EXE "0")
++endif()
++
++# Is this installation the result of a crosscompile?
++if(NOT DEFINED CMAKE_CROSSCOMPILING)
++ set(CMAKE_CROSSCOMPILING "TRUE")
++endif()
++
++# Set default install directory permissions.
++if(NOT DEFINED CMAKE_OBJDUMP)
++ set(CMAKE_OBJDUMP "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump")
++endif()
++
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/libcore.a b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/libcore.a
+new file mode 100644
+index 0000000..5959ee3
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/core/libcore.a differ
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/metadata_generation_command.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/metadata_generation_command.txt
+new file mode 100644
+index 0000000..eb20c17
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/metadata_generation_command.txt
+@@ -0,0 +1,22 @@
++ -H/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv
++-DCMAKE_SYSTEM_NAME=Android
++-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
++-DCMAKE_SYSTEM_VERSION=24
++-DANDROID_PLATFORM=android-24
++-DANDROID_ABI=arm64-v8a
++-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a
++-DANDROID_NDK=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006
++-DCMAKE_ANDROID_NDK=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006
++-DCMAKE_TOOLCHAIN_FILE=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake
++-DCMAKE_MAKE_PROGRAM=/Users/ammarahmed/Library/Android/sdk/cmake/3.22.1/bin/ninja
++-DCMAKE_CXX_FLAGS=-O3 -frtti -fexceptions -Wall -fstack-protector-all
++-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a
++-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a
++-DCMAKE_BUILD_TYPE=Debug
++-DCMAKE_FIND_ROOT_PATH=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab
++-B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a
++-GNinja
++-DANDROID_STL=c++_shared
++-DREACT_NATIVE_MINOR_VERSION=77
++ Build command args: []
++ Version: 2
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/prefab_config.json b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/prefab_config.json
+new file mode 100644
+index 0000000..2d0e64d
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/prefab_config.json
+@@ -0,0 +1,8 @@
++{
++ "enabled": true,
++ "prefabPath": "/Users/ammarahmed/.gradle/caches/modules-2/files-2.1/com.google.prefab/cli/2.1.0/aa32fec809c44fa531f01dcfb739b5b3304d3050/cli-2.1.0-all.jar",
++ "packages": [
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab",
++ "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab"
++ ]
++}
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/symbol_folder_index.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/symbol_folder_index.txt
+new file mode 100644
+index 0000000..d6b8f93
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a/symbol_folder_index.txt
+@@ -0,0 +1 @@
++/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/5w1m6j51/obj/arm64-v8a
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/hash_key.txt b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/hash_key.txt
+new file mode 100644
+index 0000000..a025bb7
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/hash_key.txt
+@@ -0,0 +1,29 @@
++# Values used to calculate the hash in this folder name.
++# Should not depend on the absolute path of the project itself.
++# - AGP: 8.7.2.
++# - $NDK is the path to NDK 27.2.12479018.
++# - $PROJECT is the path to the parent folder of the root Gradle build file.
++# - $ABI is the ABI to be built with. The specific value doesn't contribute to the value of the hash.
++# - $HASH is the hash value computed from this text.
++# - $CMAKE is the path to CMake 3.22.1.
++# - $NINJA is the path to Ninja.
++-H/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv
++-DCMAKE_SYSTEM_NAME=Android
++-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
++-DCMAKE_SYSTEM_VERSION=24
++-DANDROID_PLATFORM=android-24
++-DANDROID_ABI=$ABI
++-DCMAKE_ANDROID_ARCH_ABI=$ABI
++-DANDROID_NDK=$NDK
++-DCMAKE_ANDROID_NDK=$NDK
++-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake
++-DCMAKE_MAKE_PROGRAM=$NINJA
++-DCMAKE_CXX_FLAGS=-O3 -frtti -fexceptions -Wall -fstack-protector-all
++-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/$HASH/obj/$ABI
++-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/build/intermediates/cxx/Debug/$HASH/obj/$ABI
++-DCMAKE_BUILD_TYPE=Debug
++-DCMAKE_FIND_ROOT_PATH=/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/$HASH/prefab/$ABI/prefab
++-B/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/$HASH/$ABI
++-GNinja
++-DANDROID_STL=c++_shared
++-DREACT_NATIVE_MINOR_VERSION=77
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake
+new file mode 100644
+index 0000000..3b54b7d
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake
+@@ -0,0 +1,36 @@
++if(NOT TARGET ReactAndroid::hermestooling)
++add_library(ReactAndroid::hermestooling SHARED IMPORTED)
++set_target_properties(ReactAndroid::hermestooling PROPERTIES
++ IMPORTED_LOCATION "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/hermestooling/libs/android.arm64-v8a/libhermestooling.so"
++ INTERFACE_INCLUDE_DIRECTORIES "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/hermestooling/include"
++ INTERFACE_LINK_LIBRARIES ""
++)
++endif()
++
++if(NOT TARGET ReactAndroid::jsctooling)
++add_library(ReactAndroid::jsctooling SHARED IMPORTED)
++set_target_properties(ReactAndroid::jsctooling PROPERTIES
++ IMPORTED_LOCATION "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsctooling/libs/android.arm64-v8a/libjsctooling.so"
++ INTERFACE_INCLUDE_DIRECTORIES "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsctooling/include"
++ INTERFACE_LINK_LIBRARIES ""
++)
++endif()
++
++if(NOT TARGET ReactAndroid::jsi)
++add_library(ReactAndroid::jsi SHARED IMPORTED)
++set_target_properties(ReactAndroid::jsi PROPERTIES
++ IMPORTED_LOCATION "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/libs/android.arm64-v8a/libjsi.so"
++ INTERFACE_INCLUDE_DIRECTORIES "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/include"
++ INTERFACE_LINK_LIBRARIES ""
++)
++endif()
++
++if(NOT TARGET ReactAndroid::reactnative)
++add_library(ReactAndroid::reactnative SHARED IMPORTED)
++set_target_properties(ReactAndroid::reactnative PROPERTIES
++ IMPORTED_LOCATION "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/libs/android.arm64-v8a/libreactnative.so"
++ INTERFACE_INCLUDE_DIRECTORIES "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/include"
++ INTERFACE_LINK_LIBRARIES ""
++)
++endif()
++
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake
+new file mode 100644
+index 0000000..ceca376
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake
+@@ -0,0 +1,9 @@
++set(PACKAGE_VERSION 0.77.2)
++if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
++ set(PACKAGE_VERSION_COMPATIBLE FALSE)
++else()
++ set(PACKAGE_VERSION_COMPATIBLE TRUE)
++ if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
++ set(PACKAGE_VERSION_EXACT TRUE)
++ endif()
++endif()
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfig.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfig.cmake
+new file mode 100644
+index 0000000..dc3e49a
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfig.cmake
+@@ -0,0 +1,9 @@
++if(NOT TARGET fbjni::fbjni)
++add_library(fbjni::fbjni SHARED IMPORTED)
++set_target_properties(fbjni::fbjni PROPERTIES
++ IMPORTED_LOCATION "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.arm64-v8a/libfbjni.so"
++ INTERFACE_INCLUDE_DIRECTORIES "/Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/include"
++ INTERFACE_LINK_LIBRARIES ""
++)
++endif()
++
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfigVersion.cmake b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfigVersion.cmake
+new file mode 100644
+index 0000000..fdd188a
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/prefab/arm64-v8a/prefab/lib/aarch64-linux-android/cmake/fbjni/fbjniConfigVersion.cmake
+@@ -0,0 +1,9 @@
++set(PACKAGE_VERSION 3.22.1)
++if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
++ set(PACKAGE_VERSION_COMPATIBLE FALSE)
++else()
++ set(PACKAGE_VERSION_COMPATIBLE TRUE)
++ if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
++ set(PACKAGE_VERSION_EXACT TRUE)
++ endif()
++endif()
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/.cxx/tools/debug/arm64-v8a/compile_commands.json b/node_modules/react-native-mmkv-storage/android/.cxx/tools/debug/arm64-v8a/compile_commands.json
+new file mode 100644
+index 0000000..5a5cceb
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/.cxx/tools/debug/arm64-v8a/compile_commands.json
+@@ -0,0 +1,182 @@
++[
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -Drnmmkv_EXPORTS -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/d7d422c0963f92aa7b8a765f3bd54231/transformed/fbjni-0.7.0/prefab/modules/fbjni/include -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/jsi/include -isystem /Users/ammarahmed/.gradle/caches/8.10.2/transforms/f266411dc21cf4bb3d95238b7256dd2c/transformed/react-android-0.77.2-debug/prefab/modules/reactnative/include -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -o CMakeFiles/rnmmkv.dir/rnmmkv-adapter.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/rnmmkv-adapter.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/src/main/rnmmkv/rnmmkv-adapter.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV_IO.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_IO.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKV_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKV_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKVLog.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMKVLog_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMKVLog_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputData.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputData_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputData_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputDataCrypt.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedInputDataCrypt_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedInputDataCrypt_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/CodedOutputData.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/CodedOutputData.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/KeyValueHolder.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/KeyValueHolder.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/PBUtility.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/PBUtility.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MiniPBCoder.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MiniPBCoder_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MiniPBCoder_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MMBuffer.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MMBuffer.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/InterProcessLock.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/InterProcessLock_Win32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Win32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Win32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/InterProcessLock_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/InterProcessLock_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_Android.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Android.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Android.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_Linux.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Linux.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Linux.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_Win32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Win32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_Win32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/MemoryFile_OSX.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_OSX.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/MemoryFile_OSX.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/ThreadLock.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/ThreadLock_Win32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock_Win32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/ThreadLock_Win32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/AESCrypt.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/AESCrypt.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_aes_core.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_core.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes_core.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_cfb128.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_cfb128.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_cfb128.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_md5_dgst.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_dgst.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/aes/openssl/openssl_md5_one.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_one.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_md5_one.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/crc32/crc32_armv8.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/crc32_armv8.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/crc32_armv8.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -O3 -frtti -fexceptions -Wall -fstack-protector-all -fno-limit-debug-info -fPIC -std=c++20 -o core/CMakeFiles/core.dir/crc32/zlib/crc32.cpp.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.cpp",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/crc32/zlib/crc32.cpp"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC -o core/CMakeFiles/core.dir/aes/openssl/openssl_aesv8-armx.S.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aesv8-armx.S"
++},
++{
++ "directory": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/android/.cxx/Debug/5w1m6j51/arm64-v8a",
++ "command": "/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang -target aarch64-none-linux-android24 --sysroot=/Users/ammarahmed/Library/Android/sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -I/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core -x assembler-with-cpp -march=armv8-a+crypto -fno-limit-debug-info -fPIC -o core/CMakeFiles/core.dir/aes/openssl/openssl_aes-armv4.S.o -c /Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S",
++ "file": "/Users/ammarahmed/Work/Projects/apps/notesnook/apps/mobile/node_modules/react-native-mmkv-storage/MMKV/Core/aes/openssl/openssl_aes-armv4.S"
++}
++]
+\ No newline at end of file
+diff --git a/node_modules/react-native-mmkv-storage/android/build.gradle b/node_modules/react-native-mmkv-storage/android/build.gradle
+index abb696e..ba35baa 100644
+--- a/node_modules/react-native-mmkv-storage/android/build.gradle
++++ b/node_modules/react-native-mmkv-storage/android/build.gradle
+@@ -98,7 +98,8 @@ android {
+ cmake {
+ cppFlags "-O3 -frtti -fexceptions -Wall -fstack-protector-all"
+ arguments "-DANDROID_STL=c++_shared",
+- "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}"
++ "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
++ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
+ abiFilters (*reactNativeArchitectures())
+ }
+ }
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/results.bin b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/results.bin
+new file mode 100644
+index 0000000..7ed749e
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/results.bin
+@@ -0,0 +1 @@
++o/bundleLibRuntimeToDirDebug
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/BuildConfig.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/BuildConfig.dex
+new file mode 100644
+index 0000000..1d6377e
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/BuildConfig.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/Constants.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/Constants.dex
+new file mode 100644
+index 0000000..d654c29
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/Constants.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/MMKV.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/MMKV.dex
+new file mode 100644
+index 0000000..833403e
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/MMKV.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/MmkvStorageSpec.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/MmkvStorageSpec.dex
+new file mode 100644
+index 0000000..7d0b376
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/MmkvStorageSpec.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/RNMMKVModule.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/RNMMKVModule.dex
+new file mode 100644
+index 0000000..d016273
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/RNMMKVModule.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/RNMMKVPackage.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/RNMMKVPackage.dex
+new file mode 100644
+index 0000000..14a5234
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/RNMMKVPackage.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/SecureKeystore.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/SecureKeystore.dex
+new file mode 100644
+index 0000000..bc085ef
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/SecureKeystore.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/Storage.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/Storage.dex
+new file mode 100644
+index 0000000..c2d7d42
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/ammarahmed/mmkv/Storage.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin
+new file mode 100644
+index 0000000..601f245
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/eccc69f2d20028ee30be50f896fdd6e6/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/fa8696f116f5d031eb7dc4c90a7e1a29/results.bin b/node_modules/react-native-mmkv-storage/android/build/.transforms/fa8696f116f5d031eb7dc4c90a7e1a29/results.bin
+new file mode 100644
+index 0000000..0d259dd
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/build/.transforms/fa8696f116f5d031eb7dc4c90a7e1a29/results.bin
+@@ -0,0 +1 @@
++o/classes
+diff --git a/node_modules/react-native-mmkv-storage/android/build/.transforms/fa8696f116f5d031eb7dc4c90a7e1a29/transformed/classes/classes_dex/classes.dex b/node_modules/react-native-mmkv-storage/android/build/.transforms/fa8696f116f5d031eb7dc4c90a7e1a29/transformed/classes/classes_dex/classes.dex
+new file mode 100644
+index 0000000..2622598
+Binary files /dev/null and b/node_modules/react-native-mmkv-storage/android/build/.transforms/fa8696f116f5d031eb7dc4c90a7e1a29/transformed/classes/classes_dex/classes.dex differ
+diff --git a/node_modules/react-native-mmkv-storage/android/build/generated/source/buildConfig/debug/com/ammarahmed/mmkv/BuildConfig.java b/node_modules/react-native-mmkv-storage/android/build/generated/source/buildConfig/debug/com/ammarahmed/mmkv/BuildConfig.java
+new file mode 100644
+index 0000000..f855f1c
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/build/generated/source/buildConfig/debug/com/ammarahmed/mmkv/BuildConfig.java
+@@ -0,0 +1,12 @@
++/**
++ * Automatically generated file. DO NOT MODIFY
++ */
++package com.ammarahmed.mmkv;
++
++public final class BuildConfig {
++ public static final boolean DEBUG = Boolean.parseBoolean("true");
++ public static final String LIBRARY_PACKAGE_NAME = "com.ammarahmed.mmkv";
++ public static final String BUILD_TYPE = "debug";
++ // Field from default config.
++ public static final boolean IS_NEW_ARCHITECTURE_ENABLED = false;
++}
+diff --git a/node_modules/react-native-mmkv-storage/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml b/node_modules/react-native-mmkv-storage/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml
+new file mode 100644
+index 0000000..0a3cc21
+--- /dev/null
++++ b/node_modules/react-native-mmkv-storage/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml
+@@ -0,0 +1,7 @@
++
++
A (better) trigram tokenizer for SQLite3 FTS5
++ ++While SQLite3 already has a built-in trigram tokenizer, it does not have any kind of word segmentation support. For example, `i am a bird` gets tokenized as `['i a', ' am', 'm a', ' a ', ' bi', 'bir', 'ird']` which isn't too bad but in real-world use cases users usually type queries as `SELECT * FROM fts_table WHERE title MATCH 'a bird'` which returns no results. ++ ++This tokenizer fixes this by treating spaces as a word boundary. The result is that `i am a bird` gets tokenized as `['i', 'am', 'a', 'bir', 'ird']` and `SELECT * FROM fts_table WHERE title MATCH 'a bird'` correctly returns the expected results. You get all the benefits for substring matching just with a wider range of queries. ++ ++Furthermore, the built-in `trigram` tokenizer treats CJK as normal characters and creates trigrams out of them. The problem is, in CJK a single Unicode character can be a whole word. `better-trigram` fixes this by treating each CJK character as its own token. For example: `李红:那是钢笔` gets tokenized as `['李','红',':','那','是','钢','笔']` and if there are any non-CJK words mixed in the input, they also get properly tokenized automatically. ++ ++## Compatibility with `trigram` ++ ++`better-trigram` is 99% compatible with `trigram`. This means it has full UTF-8 support, handles all the same edge cases etc. To ensure `better-trigram` remains compatible, it passes all the `trigram` tokenizer tests. Yay! ++ ++With that being said, `better-trigram` doesn't support `LIKE` & `GLOB` patterns. This is a limitation in FTS5 because it doesn't allow custom tokenizers to opt-in to this behavior. (You _could_ technically compile a custom version of FTS5 that enables support for this but I haven't looked into it.) Using `LIKE` & `GLOB` will fallback to full table scans (not recommended). ++ ++## Usage ++ ++You can use this tokenizer like any other custom tokenizer: ++ ++```sh ++make ++``` ++ ++Load the `better-trigram.so` file as a loadable SQLite extension (e.g. `.load better-trigram.so`). ++ ++Then specify it when creating your FTS5 virtual table: ++ ++```sql ++CREATE VIRTUAL TABLE t1 USING fts5(y, tokenize='better_trigram') ++``` ++ ++### Options ++ ++`better-trigram` supports exactly the same options as `trigram` and copies the exact behavior of the original tokenizer when specifying invalid options. This means setting `case_sensitive 1` and `remove_diacritics 1` will throw an error. ++ ++Refer to [FTS5 documentation for the Trigram tokenizer](https://sqlite.org/fts5.html#the_trigram_tokenizer) for more details on what each options does and how you can use it. ++ ++## Performance ++ ++`better-trigram` is significantly faster than `trigram`. Here are the benchmarks: ++ ++``` ++Text length: 289091 ++clk: ~4.09 GHz ++cpu: AMD Ryzen 5 PRO 5650U with Radeon Graphics ++runtime: bun 1.1.31 (x64-linux) ++ ++benchmark avg (min … max) p75 p99 (min … top 1%) ++-------------------------------------- ------------------------------- ++better-trigram 6.37 ms/iter 6.86 ms 7.31 ms ▂▅▃▂▂▃▄▇█▄▂ ++trigram 10.21 ms/iter 11.23 ms 12.75 ms █▄▄▄▃▅▅▇▄▂▂ ++ ++summary ++ better-trigram ++ 1.6x faster than trigram ++``` ++ ++To reproduce on your own machine, run `bun bench.ts`. ++ ++## Contributing ++ ++All kinds of PRs are welcome, of course. Just make sure all the tests pass. You can run the tests like this: ++ ++```sh ++make test ++``` ++ ++## License ++ ++``` ++2024-10-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. ++``` +diff --git a/node_modules/react-native-quick-sqlite/better-trigram/VERSION b/node_modules/react-native-quick-sqlite/better-trigram/VERSION +new file mode 100755 +index 0000000..6812f81 +--- /dev/null ++++ b/node_modules/react-native-quick-sqlite/better-trigram/VERSION +@@ -0,0 +1 @@ ++0.0.3 +\ No newline at end of file +diff --git a/node_modules/react-native-quick-sqlite/better-trigram/bench.ts b/node_modules/react-native-quick-sqlite/better-trigram/bench.ts +new file mode 100755 +index 0000000..bd9fe70 +--- /dev/null ++++ b/node_modules/react-native-quick-sqlite/better-trigram/bench.ts +@@ -0,0 +1,44 @@ ++import { run, bench, compact, summary } from "mitata"; ++import { Database } from "bun:sqlite"; ++import { LoremIpsum } from "lorem-ipsum"; ++ ++const lorem = new LoremIpsum({ ++ sentencesPerParagraph: { ++ max: 15, ++ min: 10, ++ }, ++ wordsPerSentence: { ++ max: 50, ++ min: 20, ++ }, ++}); ++ ++const text = lorem.generateParagraphs(100); ++function initDatabase() { ++ const db = new Database(":memory:"); ++ db.loadExtension("./dist/better-trigram.so"); ++ return db; ++} ++const db = initDatabase(); ++db.query( ++ `CREATE VIRTUAL TABLE bt1 USING fts5(y, tokenize='better_trigram');` ++).run(); ++db.query(`CREATE VIRTUAL TABLE t1 USING fts5(y, tokenize='trigram');`).run(); ++const btQuery = db.query(`INSERT INTO bt1 VALUES( ? );`); ++const tQuery = db.query(`INSERT INTO t1 VALUES( ? );`); ++ ++console.log("Text length:", text.length); ++ ++compact(() => { ++ summary(() => { ++ bench("better-trigram", () => { ++ btQuery.run(text); ++ }); ++ ++ bench("trigram", () => { ++ tQuery.run(text); ++ }); ++ }); ++}); ++ ++await run(); +diff --git a/node_modules/react-native-quick-sqlite/better-trigram/better-trigram.c b/node_modules/react-native-quick-sqlite/better-trigram/better-trigram.c +new file mode 100755 +index 0000000..010fce1 +--- /dev/null ++++ b/node_modules/react-native-quick-sqlite/better-trigram/better-trigram.c +@@ -0,0 +1,151 @@ ++/* ++** 2024-10-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. ++** ++*/ ++ ++#include "better-trigram.h" ++#include "tokenizer.c" ++#include++** 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]]
Otherwise, "BINARY" is returned. + ** + */ +-SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); ++SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int); + + /* + ** CAPI3REF: Determine if a virtual table query is DISTINCT +@@ -9961,7 +10417,7 @@ SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); + ** communicated to the xBestIndex method as a + ** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use + ** this constraint, it must set the corresponding +-** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under ++** 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 +@@ -10030,21 +10486,20 @@ SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); + ** 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) must be one of the parameters to the ++** 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 use 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_MISUSE])^ or perhaps +-** exhibit some other undefined or harmful behavior. ++** 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==SQLITE_OK && pVal; + ** rc=sqlite3_vtab_in_next(pList, &pVal) + ** ){ + ** // do something with pVal +@@ -10142,6 +10597,10 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** + ** 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]]
+ */ + #define SQLITE_SCANSTAT_NLOOP 0 +@@ -10183,12 +10654,14 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** + #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 + ** +-** This interface returns information about the predicted and measured ++** 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. +@@ -10199,19 +10672,25 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** + ** + ** 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. +-** Parameter "idx" identifies the specific loop to retrieve statistics for. +-** Loops are numbered starting from zero. ^If idx is out of range - less than +-** zero or greater than or equal to the total number of loops used to implement +-** the statement - a non-zero value is returned and the variable that pOut +-** points to is unchanged. +-** +-** ^Statistics might not be available for all loops in all statements. ^In cases +-** where there exist loops with no available statistics, this function behaves +-** as if the loop did not exist - it returns non-zero and leave the variable +-** that pOut points to unchanged. ++** 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 be ++** to query for statistics regarding 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()] + */ +@@ -10221,6 +10700,19 @@ SQLITE_API int sqlite3_stmt_scanstatus( + 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 +@@ -10311,6 +10803,10 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); + ** 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 +@@ -10350,7 +10846,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*); + ** When the [sqlite3_blob_write()] API is used to update a blob column, + ** the pre-update hook is invoked with SQLITE_DELETE. This is because the + ** in this case the new values are not available. In this case, when a +-** callback made with op==SQLITE_DELETE is actuall a write using the ++** 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 +@@ -10611,6 +11107,13 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c + ** 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. +@@ -10659,6 +11162,9 @@ SQLITE_API unsigned char *sqlite3_serialize( + ** 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. +@@ -10667,6 +11173,13 @@ SQLITE_API unsigned char *sqlite3_serialize( + ** 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. +@@ -10716,11 +11229,35 @@ SQLITE_API int sqlite3_deserialize( + # undef double + #endif + ++#if defined(__wasi__) ++# undef SQLITE_WASI ++# define SQLITE_WASI 1 ++# undef SQLITE_OMIT_WAL ++# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */ ++# 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 /* SQLITE3_H */ + ++/* Function prototypes of SQLite3 Multiple Ciphers */ ++SQLITE_PRIVATE int sqlite3mcCheckVfs(const char*); ++SQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*); ++SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**); ++SQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*); ++typedef struct PgHdr PgHdrMC; ++SQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg); ++typedef struct Pager PagerMC; ++SQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager); ++SQLITE_PRIVATE void sqlite3mcInitMemoryMethods(); ++ + /******** Begin file sqlite3rtree.h *********/ + /* + ** 2010 August 30 +@@ -10922,16 +11459,20 @@ SQLITE_API int sqlite3session_create( + SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); + + /* +-** CAPIREF: Conigure a Session Object ++** 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 value for the second parameter is +-** [SQLITE_SESSION_OBJCONFIG_SIZE]. ++** created. At present the only valid values for the second parameter are ++** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID]. + ** +-** Arguments for sqlite3session_object_config() ++*/ ++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 4th parameter to ++** The following values may passed as the the 2nd parameter to + ** sqlite3session_object_config(). + ** + **- SQLITE_SCANSTAT_NLOOP
+ **- ^The [sqlite3_int64] variable pointed to by the V parameter will be +@@ -10169,12 +10628,24 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** + ** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] + ** description for the X-th loop. + ** +-** [[SQLITE_SCANSTAT_SELECTID]]
- SQLITE_SCANSTAT_SELECT
++** [[SQLITE_SCANSTAT_SELECTID]]- SQLITE_SCANSTAT_SELECTID
+ **- ^The "int" variable pointed to by the V parameter will be set to the +-** "select-id" for the X-th loop. The select-id identifies which query or +-** subquery the loop is part of. The main query has a select-id of zero. +-** The select-id is the same value as is output in the first column +-** of an [EXPLAIN QUERY PLAN] query. ++** 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 ++** 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. + **
SQLITE_SESSION_OBJCONFIG_SIZE +@@ -10947,12 +11488,21 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); + ** + ** 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. + */ +-SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); +- +-/* +-*/ +-#define SQLITE_SESSION_OBJCONFIG_SIZE 1 ++#define SQLITE_SESSION_OBJCONFIG_SIZE 1 ++#define SQLITE_SESSION_OBJCONFIG_ROWID 2 + + /* + ** CAPI3REF: Enable Or Disable A Session Object +@@ -11713,6 +12263,18 @@ SQLITE_API int sqlite3changeset_concat( + ); + + ++/* ++** CAPI3REF: Upgrade the Schema of a Changeset/Patchset ++*/ ++SQLITE_API int sqlite3changeset_upgrade( ++ sqlite3 *db, ++ const char *zDb, ++ int nIn, const void *pIn, /* Input changeset */ ++ int *pnOut, void **ppOut /* OUT: Inverse of input */ ++); ++ ++ ++ + /* + ** CAPI3REF: Changegroup Handle + ** +@@ -11759,6 +12321,38 @@ typedef struct sqlite3_changegroup sqlite3_changegroup; + */ + 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 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 +@@ -11827,13 +12421,18 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); + ** 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. 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. ++** 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 no error occurs, SQLITE_OK is returned. ++** 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); + +@@ -12085,9 +12684,30 @@ SQLITE_API int sqlite3changeset_apply_v2( + ** 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. ++** ++**- 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. ++**
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 +@@ -12653,8 +13273,11 @@ struct Fts5PhraseIter { + ** created with the "columnsize=0" option. + ** + ** xColumnText: +-** This function attempts to retrieve the text of column iCol of the +-** current document. If successful, (*pz) is set to point to a buffer ++** 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 +@@ -12664,8 +13287,10 @@ struct Fts5PhraseIter { + ** Returns the number of phrases in the current query expression. + ** + ** xPhraseSize: +-** Returns the number of tokens in phrase iPhrase of the query. Phrases +-** are numbered starting from zero. ++** 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 +@@ -12681,12 +13306,13 @@ struct Fts5PhraseIter { + ** 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(). ++** output by xInstCount(). If iIdx is less than zero or greater than ++** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned. + ** +-** Usually, output parameter *piPhrase is set to the phrase number, *piCol ++** 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. Returns SQLITE_OK if successful, or an error +-** code (i.e. SQLITE_NOMEM) if an error occurs. ++** 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. +@@ -12712,6 +13338,10 @@ struct Fts5PhraseIter { + ** 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. +@@ -12826,6 +13456,39 @@ struct Fts5PhraseIter { + ** + ** 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. This API is not available if the specified token matches a ++** prefix query term. In that case both output variables are always set ++** to 0. ++** ++** 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 can be quite slow if used with an FTS5 table created with the ++** "detail=none" or "detail=column" option. + */ + struct Fts5ExtensionApi { + int iVersion; /* Currently always set to 3 */ +@@ -12863,6 +13526,13 @@ struct Fts5ExtensionApi { + + 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*); + }; + + /* +@@ -13057,8 +13727,8 @@ struct Fts5ExtensionApi { + ** 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 (2)) or query +-** text (method (3)), not both. Doing so will not cause any errors, but is ++** 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; +@@ -13106,7 +13776,7 @@ struct fts5_api { + int (*xCreateTokenizer)( + fts5_api *pApi, + const char *zName, +- void *pContext, ++ void *pUserData, + fts5_tokenizer *pTokenizer, + void (*xDestroy)(void*) + ); +@@ -13115,7 +13785,7 @@ struct fts5_api { + int (*xFindTokenizer)( + fts5_api *pApi, + const char *zName, +- void **ppContext, ++ void **ppUserData, + fts5_tokenizer *pTokenizer + ); + +@@ -13123,7 +13793,7 @@ struct fts5_api { + int (*xCreateFunction)( + fts5_api *pApi, + const char *zName, +- void *pContext, ++ void *pUserData, + fts5_extension_function xFunction, + void (*xDestroy)(void*) + ); +@@ -13154,7 +13824,7 @@ struct fts5_api { + ** autoconf-based build + */ + #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) +-#include "config.h" ++#include "sqlite_cfg.h" + #define SQLITECONFIG_H 1 + #endif + +@@ -13234,7 +13904,7 @@ struct fts5_api { + ** level of recursion for each term. A stack overflow can result + ** if the number of terms is too large. In practice, most SQL + ** never has more than 3 or 4 terms. Use a value of 0 to disable +-** any limit on the number of terms in a compount SELECT. ++** any limit on the number of terms in a compound SELECT. + */ + #ifndef SQLITE_MAX_COMPOUND_SELECT + # define SQLITE_MAX_COMPOUND_SELECT 500 +@@ -13349,7 +14019,7 @@ struct fts5_api { + ** max_page_count macro. + */ + #ifndef SQLITE_MAX_PAGE_COUNT +-# define SQLITE_MAX_PAGE_COUNT 1073741823 ++# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */ + #endif + + /* +@@ -13384,8 +14054,8 @@ struct fts5_api { + #endif + + /* +-** WAL mode depends on atomic aligned 32-bit loads and stores in a few +-** places. The following macros try to make this explicit. ++** 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 */ +@@ -13441,15 +14111,22 @@ struct fts5_api { + #endif + + /* +-** A macro to hint to the compiler that a function should not be ++** 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 + + /* +@@ -13471,6 +14148,29 @@ struct fts5_api { + # 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 +@@ -14267,15 +14967,9 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ + + /* + ** The datatype used to store estimates of the number of rows in a +-** table or index. This is an unsigned integer type. For 99.9% of +-** the world, a 32-bit integer is sufficient. But a 64-bit integer +-** can be used at compile-time if desired. ++** table or index. + */ +-#ifdef SQLITE_64BIT_STATS +- typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ +-#else +- typedef u32 tRowcnt; /* 32-bit is the default */ +-#endif ++typedef u64 tRowcnt; + + /* + ** Estimated quantities used for query planning are stored as 16-bit +@@ -14336,8 +15030,31 @@ typedef INT16_TYPE LogEst; + ** 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))) ++#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, +@@ -14347,16 +15064,33 @@ typedef INT16_TYPE LogEst; + ** 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 +-# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ ++#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(__ppc__) || \ +- defined(__ARMEB__) || defined(__AARCH64EB__) +-# define SQLITE_BYTEORDER 4321 ++# define SQLITE_BYTEORDER 1234 ++# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__) ++# define SQLITE_BYTEORDER 4321 + # else + # define SQLITE_BYTEORDER 0 + # endif +@@ -14421,9 +15155,9 @@ typedef INT16_TYPE LogEst; + ** pointers. In that case, only verify 4-byte alignment. + */ + #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +-# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) ++# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0) + #else +-# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) ++# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) + #endif + + /* +@@ -14477,15 +15211,38 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace; + && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \ + || defined(SQLITE_ENABLE_TREETRACE)) + # define TREETRACE_ENABLED 1 +-# define SELECTTRACE(K,P,S,X) \ ++# define TREETRACE(K,P,S,X) \ + if(sqlite3TreeTrace&(K)) \ + sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\ + sqlite3DebugPrintf X + #else +-# define SELECTTRACE(K,P,S,X) ++# 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 ++*/ ++ + /* + ** Macros for "wheretrace" + */ +@@ -14498,6 +15255,36 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace; + # 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 ++** 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 adjustements ++** 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() ++*/ ++ + + /* + ** An instance of the following structure is used to store the busy-handler +@@ -14518,7 +15305,7 @@ struct BusyHandler { + /* + ** Name of table that holds the database schema. + ** +-** The PREFERRED names are used whereever possible. But LEGACY is also ++** 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 +@@ -14627,16 +15414,19 @@ 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; +@@ -14649,6 +15439,7 @@ 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; +@@ -14702,6 +15493,7 @@ typedef struct With With; + #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 +@@ -14716,6 +15508,331 @@ typedef int VList; + ** "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 *******************************************/ + /* +@@ -14936,7 +16053,7 @@ 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, int *); ++SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*); + SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); + SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); + +@@ -14960,6 +16077,10 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); + # 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 ***********************************************/ +@@ -15151,7 +16272,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p); + ** 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 extentions that use ++** standard SQLite. The other hints are provided for extensions that use + ** the SQLite parser and code generator but substitute their own storage + ** engine. + */ +@@ -15289,15 +16410,21 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); + SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); + SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*); + SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*); +-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*); +-#endif + 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 char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,Pgno*aRoot,int nRoot,int,int*); ++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 */ ++ 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*); + +@@ -15336,6 +16463,8 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); + + 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 +@@ -15452,14 +16581,14 @@ struct VdbeOp { + #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS + char *zComment; /* Comment to improve readability */ + #endif +-#ifdef VDBE_PROFILE +- u32 cnt; /* Number of times this instruction was executed */ +- u64 cycles; /* Total time spent executing this instruction */ +-#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; + +@@ -15511,6 +16640,7 @@ typedef struct VdbeOpList VdbeOpList; + #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 */ + + /* Error message codes for OP_Halt */ + #define P5_ConstraintNotNull 1 +@@ -15560,48 +16690,48 @@ typedef struct VdbeOpList VdbeOpList; + #define OP_Vacuum 5 + #define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */ + #define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */ +-#define OP_Goto 8 /* jump */ +-#define OP_Gosub 9 /* jump */ +-#define OP_InitCoroutine 10 /* jump */ +-#define OP_Yield 11 /* jump */ +-#define OP_MustBeInt 12 /* jump */ +-#define OP_Jump 13 /* jump */ +-#define OP_Once 14 /* jump */ +-#define OP_If 15 /* jump */ +-#define OP_IfNot 16 /* jump */ +-#define OP_IsNullOrType 17 /* jump, synopsis: if typeof(r[P1]) IN (P3,5) goto P2 */ +-#define OP_IfNullRow 18 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ ++#define OP_Init 8 /* jump, synopsis: Start at P2 */ ++#define OP_Goto 9 /* jump */ ++#define OP_Gosub 10 /* jump */ ++#define OP_InitCoroutine 11 /* jump */ ++#define OP_Yield 12 /* jump */ ++#define OP_MustBeInt 13 /* jump */ ++#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_SeekLT 20 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekLE 21 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekGE 22 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekGT 23 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IfNotOpen 24 /* jump, synopsis: if( !csr[P1] ) goto P2 */ +-#define OP_IfNoHope 25 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_NoConflict 26 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_NotFound 27 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_Found 28 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_SeekRowid 29 /* jump, synopsis: intkey=r[P3] */ +-#define OP_NotExists 30 /* jump, synopsis: intkey=r[P3] */ +-#define OP_Last 31 /* jump */ +-#define OP_IfSmaller 32 /* jump */ +-#define OP_SorterSort 33 /* jump */ +-#define OP_Sort 34 /* jump */ +-#define OP_Rewind 35 /* jump */ +-#define OP_SorterNext 36 /* jump */ +-#define OP_Prev 37 /* jump */ +-#define OP_Next 38 /* jump */ +-#define OP_IdxLE 39 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IdxGT 40 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IdxLT 41 /* jump, synopsis: key=r[P3@P4] */ +-#define OP_IdxGE 42 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ ++#define OP_SeekLT 21 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekLE 22 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekGE 23 /* jump, synopsis: key=r[P3@P4] */ ++#define OP_SeekGT 24 /* jump, 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 /* jump, synopsis: intkey=r[P3] */ ++#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */ ++#define OP_Last 32 /* jump */ ++#define OP_IfSmaller 33 /* jump */ ++#define OP_SorterSort 34 /* jump */ ++#define OP_Sort 35 /* jump */ ++#define OP_Rewind 36 /* jump */ ++#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_RowSetRead 45 /* jump, synopsis: r[P3]=rowset(P1) */ +-#define OP_RowSetTest 46 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ +-#define OP_Program 47 /* jump */ +-#define OP_FkIfZero 48 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ +-#define OP_IfPos 49 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ ++#define OP_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 /* jump */ ++#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ + #define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ + #define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ + #define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ +@@ -15611,12 +16741,12 @@ typedef struct VdbeOpList VdbeOpList; + #define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3] =r[P1] */ + #define OP_ElseEq 58 /* jump, same as TK_ESCAPE */ +-#define OP_IfNotZero 59 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ +-#define OP_DecrJumpZero 60 /* jump, synopsis: if (--r[P1])==0 goto P2 */ +-#define OP_IncrVacuum 61 /* jump */ +-#define OP_VNext 62 /* jump */ +-#define OP_Filter 63 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */ +-#define OP_Init 64 /* jump, synopsis: Start at P2 */ ++#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ ++#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 +@@ -15726,19 +16856,22 @@ typedef struct VdbeOpList VdbeOpList; + #define OP_VCreate 171 + #define OP_VDestroy 172 + #define OP_VOpen 173 +-#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */ +-#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */ +-#define OP_VRename 176 +-#define OP_Pagecount 177 +-#define OP_MaxPgcnt 178 +-#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */ +-#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */ +-#define OP_Trace 181 +-#define OP_CursorHint 182 +-#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */ +-#define OP_Noop 184 +-#define OP_Explain 185 +-#define OP_Abortable 186 ++#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 +@@ -15750,31 +16883,32 @@ typedef struct VdbeOpList VdbeOpList; + #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_INITIALIZER {\ +-/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\ +-/* 8 */ 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03,\ +-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x09, 0x09, 0x09, 0x09,\ +-/* 24 */ 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x01,\ +-/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ +-/* 40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x23, 0x0b, 0x01,\ +-/* 48 */ 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ +-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01,\ ++/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\ ++/* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\ ++/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\ ++/* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\ ++/* 32 */ 0x41, 0x01, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41,\ ++/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\ ++/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ ++/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 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, 0x00, 0x00,\ +-/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x26, 0x26,\ ++/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\ ++/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\ + /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ +-/* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\ +-/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ +-/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ +-/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\ ++/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 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, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ + /* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +-/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\ +-/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\ +-/* 184 */ 0x00, 0x00, 0x00,} ++/* 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 +@@ -15827,14 +16961,20 @@ SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int); + #endif + SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); + #ifndef SQLITE_OMIT_EXPLAIN +-SQLITE_PRIVATE void sqlite3VdbeExplain(Parse*,u8,const char*,...); ++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*/ +@@ -15850,6 +16990,7 @@ 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); +@@ -15864,6 +17005,7 @@ 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*); +@@ -15941,7 +17083,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); + ** The VdbeCoverage macros are used to set a coverage testing point + ** for VDBE branch instructions. The coverage testing points are line + ** numbers in the sqlite3.c source file. VDBE branch coverage testing +-** only works with an amalagmation build. That's ok since a VDBE branch ++** 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. + ** +@@ -15959,7 +17101,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); + ** // NULL option is not possible + ** + ** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested +-** // in distingishing equal and not-equal. ++** // 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 +@@ -15969,7 +17111,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); + ** 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 ov the VdbeCoverage macro and ++** 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. +@@ -16005,14 +17147,22 @@ SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int); + + #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) ++# 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 ************************************************/ +@@ -16061,7 +17211,7 @@ struct PgHdr { + ** private to pcache.c and should not be accessed by other modules. + ** pCache is grouped with the public elements for efficiency. + */ +- i16 nRef; /* Number of users of this page */ ++ 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 +@@ -16142,12 +17292,12 @@ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); + SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); + + /* Return the total number of outstanding page references */ +-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); ++SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache*); + + /* Increment the reference count of an existing page */ + SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); + +-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); ++SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr*); + + /* Return the total number of pages stored in the cache */ + SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); +@@ -16212,297 +17362,6 @@ SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); + + /************** End of pcache.h **********************************************/ + /************** Continuing where we left off in sqliteInt.h ******************/ +-/************** Include os.h in the middle of sqliteInt.h ********************/ +-/************** Begin file os.h **********************************************/ +-/* +-** 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_UNIX, +-** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of +-** the three will be 1. The other two will be 0. +-*/ +-#if defined(SQLITE_OS_OTHER) +-# if SQLITE_OS_OTHER==1 +-# undef SQLITE_OS_UNIX +-# define SQLITE_OS_UNIX 0 +-# undef SQLITE_OS_WIN +-# define SQLITE_OS_WIN 0 +-# else +-# undef SQLITE_OS_OTHER +-# endif +-#endif +-#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +-# define SQLITE_OS_OTHER 0 +-# ifndef SQLITE_OS_WIN +-# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ +- defined(__MINGW32__) || defined(__BORLANDC__) +-# define SQLITE_OS_WIN 1 +-# define SQLITE_OS_UNIX 0 +-# else +-# define SQLITE_OS_WIN 0 +-# define SQLITE_OS_UNIX 1 +-# endif +-# else +-# define SQLITE_OS_UNIX 0 +-# endif +-#else +-# ifndef SQLITE_OS_WIN +-# define SQLITE_OS_WIN 0 +-# endif +-#endif +- +-#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 mutex.h in the middle of sqliteInt.h *****************/ + /************** Begin file mutex.h *******************************************/ + /* +@@ -16591,7 +17450,7 @@ SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); + /* + ** Default synchronous levels. + ** +-** Note that (for historcal reasons) the PAGER_SYNCHRONOUS_* macros differ ++** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ + ** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1. + ** + ** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS +@@ -16630,7 +17489,7 @@ struct Db { + ** 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 databaes (sqlite3.aDb[1]) which is free-standing. ++** 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. + ** +@@ -16741,13 +17600,14 @@ struct Lookaside { + 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 prediously used */ ++ 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 */ +@@ -16757,7 +17617,7 @@ struct LookasideSlot { + #define EnableLookaside db->lookaside.bDisable--;\ + db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue + +-/* Size of the smaller allocations in two-size lookside */ ++/* Size of the smaller allocations in two-size lookaside */ + #ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE + # define LOOKASIDE_SMALL 0 + #else +@@ -16957,6 +17817,7 @@ struct sqlite3 { + 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. +@@ -17012,7 +17873,7 @@ struct sqlite3 { + #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_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */ ++#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 */ +@@ -17038,6 +17899,8 @@ struct sqlite3 { + /* 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 */ + + /* Flags used only if debugging */ + #ifdef SQLITE_DEBUG +@@ -17092,6 +17955,10 @@ struct sqlite3 { + #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_AllOpts 0xffffffff /* All optimizations */ + + /* +@@ -17174,10 +18041,17 @@ struct FuncDestructor { + ** 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 ++** 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 */ +@@ -17186,6 +18060,7 @@ struct FuncDestructor { + #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 */ +@@ -17194,14 +18069,15 @@ struct FuncDestructor { + #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a + ** single query - might change over time */ + #define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ +-/* 0x8000 -- available for reuse */ ++#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 */ +-#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ ++/* 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 */ +@@ -17293,10 +18169,11 @@ struct FuncDestructor { + #define MFUNCTION(zName, nArg, xPtr, xFunc) \ + {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ + xPtr, 0, xFunc, 0, 0, 0, #zName, {0} } +-#define JFUNCTION(zName, nArg, iArg, xFunc) \ +- {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|\ +- SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ +- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } ++#define 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), \ +@@ -17486,6 +18363,7 @@ struct CollSeq { + #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 sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +@@ -17556,6 +18434,7 @@ struct VTable { + 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) */ +@@ -17664,7 +18543,7 @@ struct Table { + #ifndef SQLITE_OMIT_VIRTUALTABLE + # define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB) + # define ExprIsVtab(X) \ +- ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB) ++ ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB) + #else + # define IsVirtual(X) 0 + # define ExprIsVtab(X) 0 +@@ -17763,7 +18642,7 @@ struct FKey { + ** foreign key. + ** + ** The OE_Default value is a place holder that means to use whatever +-** conflict resolution algorthm is required from context. ++** conflict resolution algorithm is required from context. + ** + ** The following symbolic values are used to record which type + ** of conflict resolution action to take. +@@ -17881,10 +18760,22 @@ struct UnpackedRecord { + ** 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 indicate the which conflict resolution +-** algorithm to employ whenever an attempt is made to insert a non-unique ++** 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 +@@ -17917,18 +18808,22 @@ struct Index { + 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 bLowQual:1; /* sqlite_stat1 says this is a low-quality index */ + 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; /* 0 for unindexed columns in pTab */ ++ Bitmask colNotIdxed; /* Unindexed columns in pTab */ + }; + + /* +@@ -18003,16 +18898,15 @@ struct AggInfo { + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ ++ u16 nSortingColumn; /* Number of columns in the sorting index */ + int sortingIdx; /* Cursor number of the sorting index */ + int sortingIdxPTab; /* Cursor number of pseudo-table */ +- int nSortingColumn; /* Number of columns in the sorting index */ +- int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */ ++ 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 iMem; /* Memory location that acts as accumulator */ + i16 iColumn; /* Column number within the source table */ + i16 iSorterColumn; /* Column number in the sorting index */ + } *aCol; +@@ -18023,14 +18917,31 @@ struct AggInfo { + struct AggInfo_func { /* For each aggregate function */ + Expr *pFExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ +- int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephemeral table used to enforce DISTINCT */ + int iDistAddr; /* Address of OP_OpenEphemeral */ ++ 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. ++*/ ++#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I)) ++#define AggInfoFuncReg(A,I) \ ++ (assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I)) ++ + /* + ** 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 +@@ -18150,7 +19061,7 @@ struct Expr { + ** TK_REGISTER: register number + ** TK_TRIGGER: 1 -> new, 0 -> old + ** EP_Unlikely: 134217728 times likelihood +- ** TK_IN: ephemerial table holding RHS ++ ** 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. +@@ -18196,7 +19107,7 @@ struct Expr { + #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_MemToken 0x020000 /* Need to sqlite3DbFree() Expr.zToken */ ++#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 */ +@@ -18226,12 +19137,15 @@ struct Expr { + #define ExprClearProperty(E,P) (E)->flags&=~(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) +@@ -18341,6 +19255,7 @@ struct ExprList { + #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, +@@ -18381,6 +19296,14 @@ struct IdList { + ** 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. ++** + ** Union member validity: + ** + ** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc +@@ -18412,7 +19335,7 @@ struct SrcItem { + unsigned notCte :1; /* This item may not match a CTE */ + unsigned isUsing :1; /* u3.pUsing is valid */ + unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ +- unsigned isSynthUsing :1; /* u3.pUsing is synthensized from NATURAL */ ++ unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */ + unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ + } fg; + int iCursor; /* The VDBE cursor number used to access this table */ +@@ -18420,14 +19343,14 @@ struct SrcItem { + Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */ + IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */ + } u3; +- Bitmask colUsed; /* Bit N (1< 62 */ + union { + char *zIndexedBy; /* Identifier from "INDEXED BY " clause */ + ExprList *pFuncArg; /* Arguments to table-valued-function */ + } u1; + union { + Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */ +- CteUse *pCteUse; /* CTE Usage info info fg.isCte is true */ ++ CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */ + } u2; + }; + +@@ -18441,23 +19364,11 @@ struct OnOrUsing { + }; + + /* +-** The following structure describes the FROM clause of a SELECT statement. +-** Each table or subquery in the FROM clause is a separate element of +-** the SrcList.a[] array. ++** 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. + ** +-** With the addition of multiple database support, the following structure +-** can also be used to describe a particular table such as the table that +-** is modified by an INSERT, DELETE, or UPDATE statement. In standard SQL, +-** such a table must be a simple name: ID. But in SQLite, the table can +-** now be identified by a database name, a dot, then the table name: ID.ID. +-** +-** 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. + */ + struct SrcList { + int nSrc; /* Number of tables or subqueries in the FROM clause */ +@@ -18545,6 +19456,7 @@ struct NameContext { + 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 */ + }; + +@@ -18565,7 +19477,7 @@ struct NameContext { + #define NC_HasAgg 0x000010 /* One or more aggregate functions seen */ + #define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */ + #define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */ +-#define NC_VarSelect 0x000040 /* A correlated subquery has been seen */ ++#define NC_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 */ +@@ -18694,6 +19606,7 @@ struct Select { + #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 */ + + /* True if S exists and has SF_NestedFrom */ + #define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0) +@@ -18802,7 +19715,7 @@ struct SelectDest { + 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 when eDest==SRT_Set */ ++ char *zAffSdst; /* Affinity used for SRT_Set */ + ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ + }; + +@@ -18861,11 +19774,34 @@ struct TriggerPrg { + #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 ++# 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 +@@ -18908,10 +19844,13 @@ struct Parse { + u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ + u8 okConstFactor; /* OK to factor out constants */ + u8 disableLookaside; /* Number of times lookaside has been disabled */ +- u8 disableVtab; /* Disable all virtual tables for this parse */ ++ u8 prepFlags; /* SQLITE_PREPARE_* flags */ + u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ + #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 */ + #endif + int nRangeReg; /* Size of the temporary register block */ + int iRangeReg; /* First register in temporary register block */ +@@ -18925,6 +19864,8 @@ struct Parse { + 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 */ + Token constraintName;/* Name of the constraint currently being parsed */ + yDbMask writeMask; /* Start a write transaction on these databases */ + yDbMask cookieMask; /* Bitmask of schema verified databases */ +@@ -18932,6 +19873,9 @@ struct Parse { + int regRoot; /* Register holding root page number for new objects */ + int nMaxArg; /* Max args passed to user function by sub-program */ + 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 */ +@@ -18945,9 +19889,9 @@ struct Parse { + int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ + Returning *pReturning; /* The RETURNING clause */ + } u1; +- u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ + u32 oldmask; /* Mask of old.* columns referenced */ + u32 newmask; /* Mask of new.* columns referenced */ ++ LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ + u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ + u8 bReturning; /* Coding a RETURNING trigger */ + u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ +@@ -19071,6 +20015,7 @@ struct AuthContext { + #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 */ +@@ -19192,6 +20137,7 @@ struct Returning { + 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" */ + }; + + /* +@@ -19213,6 +20159,28 @@ struct sqlite3_str { + + #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 +@@ -19239,7 +20207,7 @@ typedef struct { + /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled + ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning + ** parameters are for temporary use during development, to help find +-** optimial values for parameters in the query planner. The should not ++** 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. + ** +@@ -19265,6 +20233,10 @@ struct Sqlite3Config { + 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 */ ++ u8 bUseLongDouble; /* Make use of long double */ ++#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 */ +@@ -19351,6 +20323,7 @@ struct Walker { + 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 */ +@@ -19360,15 +20333,16 @@ struct Walker { + struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */ + int *aiCol; /* array of column indexes */ + struct IdxCover *pIdxCover; /* Check for index coverage */ +- struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ + 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; ++ DbFixer *pFix; /* See sqlite3FixSelect() */ ++ Mem *aMem; /* See sqlite3BtreeCursorHint() */ + } u; + }; + +@@ -19389,6 +20363,7 @@ struct DbFixer { + + /* 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*); +@@ -19469,6 +20444,16 @@ struct CteUse { + }; + + ++/* 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[1]; /* Name of this client data. MUST BE LAST */ ++}; ++ + #ifdef SQLITE_DEBUG + /* + ** An instance of the TreeView object is used for printing the content of +@@ -19638,6 +20623,8 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); + # 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)) +@@ -19647,6 +20634,8 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); + # 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); + +@@ -19674,6 +20663,7 @@ 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); +@@ -19694,12 +20684,14 @@ SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); + */ + #ifdef SQLITE_USE_ALLOCA + # define sqlite3StackAllocRaw(D,N) alloca(N) +-# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N) ++# define sqlite3StackAllocRawNN(D,N) alloca(N) + # define sqlite3StackFree(D,P) ++# define sqlite3StackFreeNN(D,P) + #else + # define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) +-# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(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 +@@ -19763,6 +20755,20 @@ struct PrintfArguments { + 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) +@@ -19822,6 +20828,7 @@ SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*); + #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*); +@@ -19836,6 +20843,10 @@ 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 +@@ -19847,9 +20858,12 @@ 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 void sqlite3ExprDeferredDelete(Parse*, Expr*); + SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); + SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); +@@ -19859,6 +20873,7 @@ 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**); +@@ -19879,7 +20894,7 @@ 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 sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); ++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*); +@@ -19949,6 +20964,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask); + 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); +@@ -19985,8 +21001,9 @@ 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*, int); ++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*); +@@ -20048,7 +21065,7 @@ 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); ++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*); +@@ -20075,7 +21092,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); + SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); + SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); + SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); +-SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*); ++SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int); + #ifdef SQLITE_ENABLE_CURSOR_HINTS + SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); + #endif +@@ -20083,6 +21100,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*); + 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); +@@ -20197,8 +21215,10 @@ 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 void sqlite3Int64ToText(i64,char*); ++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*); +@@ -20208,6 +21228,7 @@ SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, 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); +@@ -20243,11 +21264,13 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v); + + + 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*,...); +@@ -20264,6 +21287,9 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int); + + #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); +@@ -20295,6 +21321,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); + 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*)); +@@ -20314,7 +21341,6 @@ 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 sqlite3StdTypeMap[]; + SQLITE_PRIVATE const char *sqlite3StdType[]; + SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; + SQLITE_PRIVATE const unsigned char *sqlite3aLTb; +@@ -20347,7 +21373,8 @@ SQLITE_PRIVATE int sqlite3MatchEName( + const struct ExprList_item*, + const char*, + const char*, +- const char* ++ const char*, ++ int* + ); + SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*); + SQLITE_PRIVATE u8 sqlite3StrIHash(const char*); +@@ -20403,8 +21430,13 @@ 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*, 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*); +@@ -20518,10 +21550,7 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); + SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); + + SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); +-#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ +- && !defined(SQLITE_OMIT_VIRTUALTABLE) +-SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info*); +-#endif ++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 *); +@@ -20546,6 +21575,7 @@ 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) +@@ -20657,6 +21687,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int); + #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); +@@ -20758,6 +21789,22 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*); + 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 *******************************************/ +@@ -20799,101 +21846,6 @@ SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt); + */ + #ifdef SQLITE_PERFORMANCE_TRACE + +-/* +-** hwtime.h contains inline assembler code for implementing +-** high-performance timing routines. +-*/ +-/************** Include hwtime.h in the middle of os_common.h ****************/ +-/************** Begin file hwtime.h ******************************************/ +-/* +-** 2008 May 27 +-** +-** The author disclaims copyright to this source code. In place of +-** a legal notice, here is a blessing: +-** +-** May you do good and not evil. +-** May you find forgiveness for yourself and forgive others. +-** May you share freely, never taking more than you give. +-** +-****************************************************************************** +-** +-** This file contains inline asm code for retrieving "high-performance" +-** counters for x86 and x86_64 class CPUs. +-*/ +-#ifndef SQLITE_HWTIME_H +-#define SQLITE_HWTIME_H +- +-/* +-** The following routine only works on pentium-class (or newer) processors. +-** It uses the RDTSC opcode to read the cycle count value out of the +-** processor and returns that value. This can be used for high-res +-** profiling. +-*/ +-#if !defined(__STRICT_ANSI__) && \ +- (defined(__GNUC__) || defined(_MSC_VER)) && \ +- (defined(i386) || defined(__i386__) || defined(_M_IX86)) +- +- #if defined(__GNUC__) +- +- __inline__ sqlite_uint64 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 long val; +- __asm__ __volatile__ ("rdtsc" : "=A" (val)); +- return val; +- } +- +-#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 os_common.h ******************/ +- + static sqlite_uint64 g_start; + static sqlite_uint64 g_elapsed; + #define TIMER_START g_start=sqlite3Hwtime() +@@ -20989,7 +21941,7 @@ SQLITE_API extern int sqlite3_open_file_count; + ** autoconf-based build + */ + #if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) +-/* #include "config.h" */ ++/* #include "sqlite_cfg.h" */ + #define SQLITECONFIG_H 1 + #endif + +@@ -21021,9 +21973,6 @@ static const char * const sqlite3azCompileOpt[] = { + #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC + "4_BYTE_ALIGNED_MALLOC", + #endif +-#ifdef SQLITE_64BIT_STATS +- "64BIT_STATS", +-#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), +@@ -21154,6 +22103,9 @@ static const char * const sqlite3azCompileOpt[] = { + #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 +@@ -21316,6 +22268,9 @@ static const char * const sqlite3azCompileOpt[] = { + #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 +@@ -21357,6 +22312,9 @@ static const char * const sqlite3azCompileOpt[] = { + #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 +@@ -21594,6 +22552,9 @@ static const char * const sqlite3azCompileOpt[] = { + #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 +@@ -21644,9 +22605,6 @@ static const char * const sqlite3azCompileOpt[] = { + #ifdef SQLITE_OMIT_XFER_OPT + "OMIT_XFER_OPT", + #endif +-#ifdef SQLITE_PCACHE_SEPARATE_HEADER +- "PCACHE_SEPARATE_HEADER", +-#endif + #ifdef SQLITE_PERFORMANCE_TRACE + "PERFORMANCE_TRACE", + #endif +@@ -21848,7 +22806,7 @@ SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP + ** isalnum() 0x06 + ** isxdigit() 0x08 + ** toupper() 0x20 +-** SQLite identifier character 0x40 ++** SQLite identifier character 0x40 $, _, or non-ascii + ** Quote character 0x80 + ** + ** Bit 0x20 is set if the mapped character requires translation to upper +@@ -21994,6 +22952,10 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { + SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ + 0, /* bSmallMalloc */ + 1, /* bExtraSchemaChecks */ ++ sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ ++#ifdef SQLITE_DEBUG ++ 0, /* bJsonSelfcheck */ ++#endif + 0x7ffffffe, /* mxStrlen */ + 0, /* neverCorrupt */ + SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ +@@ -22042,7 +23004,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { + SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ + 0, /* iPrngSeed */ + #ifdef SQLITE_DEBUG +- {0,0,0,0,0,0} /* aTune */ ++ {0,0,0,0,0,0}, /* aTune */ + #endif + }; + +@@ -22126,10 +23088,6 @@ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; + ** + ** sqlite3StdTypeAffinity[] The affinity associated with each entry + ** in sqlite3StdType[]. +-** +-** sqlite3StdTypeMap[] The type value (as returned from +-** sqlite3_column_type() or sqlite3_value_type()) +-** for each entry in sqlite3StdType[]. + */ + SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 }; + SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = { +@@ -22140,14 +23098,6 @@ SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = { + SQLITE_AFF_REAL, + SQLITE_AFF_TEXT + }; +-SQLITE_PRIVATE const char sqlite3StdTypeMap[] = { +- 0, +- SQLITE_BLOB, +- SQLITE_INTEGER, +- SQLITE_INTEGER, +- SQLITE_FLOAT, +- SQLITE_TEXT +-}; + SQLITE_PRIVATE const char *sqlite3StdType[] = { + "ANY", + "BLOB", +@@ -22235,6 +23185,9 @@ 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 +@@ -22266,6 +23219,7 @@ struct VdbeCursor { + 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 */ +@@ -22306,6 +23260,7 @@ struct VdbeCursor { + #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 */ + + /* 2*nField extra array elements allocated for aType[], beyond the one + ** static element declared in the structure. nField total array slots for +@@ -22318,12 +23273,25 @@ struct VdbeCursor { + #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 +@@ -22350,7 +23318,6 @@ 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 */ +- i64 *anExec; /* Event counters from 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 */ +@@ -22566,10 +23533,19 @@ typedef unsigned bft; /* Bit Field Type */ + + /* 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 */ +@@ -22599,7 +23575,7 @@ struct DblquoteStr { + */ + struct Vdbe { + sqlite3 *db; /* The database connection that owns this statement */ +- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ ++ 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 */ +@@ -22625,7 +23601,7 @@ struct Vdbe { + int nOp; /* Number of instructions in the program */ + int nOpAlloc; /* Slots allocated for aOp[] */ + Mem *aColName; /* Column names to return */ +- Mem *pResultSet; /* Pointer to an array of results */ ++ Mem *pResultRow; /* Current output row */ + char *zErrMsg; /* Error message written here */ + VList *pVList; /* Name of variables */ + #ifndef SQLITE_OMIT_TRACE +@@ -22636,16 +23612,18 @@ struct Vdbe { + u32 nWrite; /* Number of write operations that have occurred */ + #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; /* True if EXPLAIN present on SQL command */ ++ 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() */ +@@ -22662,7 +23640,6 @@ struct Vdbe { + SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ + AuxData *pAuxData; /* Linked list of auxdata allocations */ + #ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- i64 *anExec; /* Number of times each op has been executed */ + int nScan; /* Entries in aScan[] */ + ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ + #endif +@@ -22693,7 +23670,7 @@ struct PreUpdate { + i64 iKey1; /* First key value passed to hook */ + i64 iKey2; /* Second key value passed to hook */ + Mem *aNew; /* Array of new.* values */ +- Table *pTab; /* Schema object being upated */ ++ Table *pTab; /* Schema object being updated */ + Index *pPk; /* PK index if pTab is WITHOUT ROWID */ + }; + +@@ -22783,6 +23760,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); + 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); +@@ -22829,6 +23807,8 @@ 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*); +@@ -23157,6 +24137,8 @@ SQLITE_API int sqlite3_db_status( + + sqlite3BtreeEnterAll(db); + db->pnBytesFreed = &nByte; ++ assert( db->lookaside.pEnd==db->lookaside.pTrueEnd ); ++ db->lookaside.pEnd = db->lookaside.pStart; + for(i=0; i nDb; i++){ + Schema *pSchema = db->aDb[i].pSchema; + if( ALWAYS(pSchema!=0) ){ +@@ -23182,6 +24164,7 @@ SQLITE_API int sqlite3_db_status( + } + } + db->pnBytesFreed = 0; ++ db->lookaside.pEnd = db->lookaside.pTrueEnd; + sqlite3BtreeLeaveAll(db); + + *pHighwater = 0; +@@ -23199,9 +24182,12 @@ SQLITE_API int sqlite3_db_status( + int nByte = 0; /* Used to accumulate return value */ + + db->pnBytesFreed = &nByte; +- for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ ++ 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 */ +@@ -23222,7 +24208,7 @@ SQLITE_API int sqlite3_db_status( + case SQLITE_DBSTATUS_CACHE_MISS: + case SQLITE_DBSTATUS_CACHE_WRITE:{ + int i; +- int nRet = 0; ++ u64 nRet = 0; + assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); + assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); + +@@ -23235,7 +24221,7 @@ SQLITE_API int sqlite3_db_status( + *pHighwater = 0; /* IMP: R-42420-56072 */ + /* IMP: R-54100-20147 */ + /* IMP: R-29431-39229 */ +- *pCurrent = nRet; ++ *pCurrent = (int)nRet & 0x7fffffff; + break; + } + +@@ -23338,6 +24324,7 @@ struct DateTime { + char validTZ; /* True (1) if tz is valid */ + char tzSet; /* Timezone was set explicitly */ + char isError; /* An overflow has occurred */ ++ char useSubsec; /* Display subsecond precision */ + }; + + +@@ -23370,8 +24357,8 @@ struct DateTime { + */ + 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, 9999 }; ++ ** 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; +@@ -23537,7 +24524,7 @@ static void computeJD(DateTime *p){ + 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); ++ p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5); + if( p->validTZ ){ + p->iJD -= p->tz*60000; + p->validYMD = 0; +@@ -23652,6 +24639,11 @@ static int parseDateOrTime( + }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; + } +@@ -23707,17 +24699,14 @@ static void computeYMD(DateTime *p){ + ** Compute the Hour, Minute, and Seconds from the julian day number. + */ + static void computeHMS(DateTime *p){ +- int s; ++ int day_ms, day_min; /* milliseconds, minutes into the day */ + if( p->validHMS ) return; + computeJD(p); +- s = (int)((p->iJD + 43200000) % 86400000); +- p->s = s/1000.0; +- s = (int)p->s; +- p->s -= s; +- p->h = s/3600; +- s -= p->h*3600; +- p->m = s/60; +- p->s += s - p->m*60; ++ 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; + } +@@ -23896,6 +24885,25 @@ static const struct { + { 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: +@@ -23939,19 +24947,8 @@ static int parseModifier( + */ + if( sqlite3_stricmp(z, "auto")==0 ){ + if( idx>1 ) return 1; /* IMP: R-33611-57934 */ +- if( !p->rawS || p->validJD ){ +- rc = 0; +- p->rawS = 0; +- }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */ +- && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */ +- ){ +- r = p->s*1000.0 + 210866760000000.0; +- clearYMD_HMS_TZ(p); +- p->iJD = (sqlite3_int64)(r + 0.5); +- p->validJD = 1; +- p->rawS = 0; +- rc = 0; +- } ++ autoAdjustDate(p); ++ rc = 0; + } + break; + } +@@ -24010,7 +25007,7 @@ static int parseModifier( + i64 iOrigJD; /* Original localtime */ + i64 iGuess; /* Guess at the corresponding utc time */ + int cnt = 0; /* Safety to prevent infinite loop */ +- int iErr; /* Guess is off by this much */ ++ i64 iErr; /* Guess is off by this much */ + + computeJD(p); + iGuess = iOrigJD = p->iJD; +@@ -24046,7 +25043,7 @@ static int parseModifier( + */ + if( sqlite3_strnicmp(z, "weekday ", 8)==0 + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0 +- && (n=(int)r)==r && n>=0 && r<7 ){ ++ && r>=0.0 && r<7.0 && (n=(int)r)==r ){ + sqlite3_int64 Z; + computeYMD_HMS(p); + p->validTZ = 0; +@@ -24066,8 +25063,22 @@ static int parseModifier( + ** + ** 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 ) break; ++ 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); +@@ -24103,18 +25114,73 @@ static int parseModifier( + case '9': { + double rRounder; + int i; +- for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} ++ 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 ){ +- rc = 1; ++ assert( rc==1 ); + break; + } +- if( z[n]==':' ){ ++ 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; ++ 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. + */ +- const char *z2 = z; ++ + DateTime tx; + sqlite3_int64 day; + if( !sqlite3Isdigit(*z2) ) z2++; +@@ -24124,7 +25190,7 @@ static int parseModifier( + tx.iJD -= 43200000; + day = tx.iJD/86400000; + tx.iJD -= day*86400000; +- if( z[0]=='-' ) tx.iJD = -tx.iJD; ++ if( z0=='-' ) tx.iJD = -tx.iJD; + computeJD(p); + clearYMD_HMS_TZ(p); + p->iJD += tx.iJD; +@@ -24140,7 +25206,7 @@ static int parseModifier( + if( n>10 || n<3 ) break; + if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; + computeJD(p); +- rc = 1; ++ assert( rc==1 ); + rRounder = r<0 ? -0.5 : +0.5; + for(i=0; i M += (int)r; +@@ -24225,6 +25290,12 @@ static int isDate( + } + computeJD(p); + if( p->isError || !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; + } + +@@ -24265,7 +25336,11 @@ static void unixepochFunc( + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + computeJD(&x); +- sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000); ++ 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); ++ } + } + } + +@@ -24281,8 +25356,8 @@ static void datetimeFunc( + ){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ +- int Y, s; +- char zBuf[24]; ++ int Y, s, n; ++ char zBuf[32]; + computeYMD_HMS(&x); + Y = x.Y; + if( Y<0 ) Y = -Y; +@@ -24303,15 +25378,28 @@ static void datetimeFunc( + zBuf[15] = '0' + (x.m/10)%10; + zBuf[16] = '0' + (x.m)%10; + zBuf[17] = ':'; +- s = (int)x.s; +- zBuf[18] = '0' + (s/10)%10; +- zBuf[19] = '0' + (s)%10; +- zBuf[20] = 0; ++ if( x.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, 20, SQLITE_TRANSIENT); ++ sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT); + }else{ +- sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT); ++ sqlite3_result_text(context, &zBuf[1], n-1, SQLITE_TRANSIENT); + } + } + } +@@ -24328,7 +25416,7 @@ static void timeFunc( + ){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ +- int s; ++ int s, n; + char zBuf[16]; + computeHMS(&x); + zBuf[0] = '0' + (x.h/10)%10; +@@ -24337,11 +25425,24 @@ static void timeFunc( + zBuf[3] = '0' + (x.m/10)%10; + zBuf[4] = '0' + (x.m)%10; + zBuf[5] = ':'; +- s = (int)x.s; +- zBuf[6] = '0' + (s/10)%10; +- zBuf[7] = '0' + (s)%10; +- zBuf[8] = 0; +- sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT); ++ 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); + } + } + +@@ -24396,7 +25497,7 @@ static void dateFunc( + ** %M minute 00-59 + ** %s seconds since 1970-01-01 + ** %S seconds 00-59 +-** %w day of week 0-6 sunday==0 ++** %w day of week 0-6 Sunday==0 + ** %W week of year 00-53 + ** %Y year 0000-9999 + ** %% % +@@ -24422,13 +25523,16 @@ static void strftimeFunc( + computeJD(&x); + computeYMD_HMS(&x); + for(i=j=0; zFmt[i]; i++){ ++ char cf; + if( zFmt[i]!='%' ) continue; + if( j12 ) h -= 12; ++ if( h==0 ) h = 12; ++ sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); + break; + } + case 'W': /* Fall thru */ +@@ -24450,7 +25567,7 @@ static void strftimeFunc( + y.D = 1; + computeJD(&y); + nDay = (int)((x.iJD-y.iJD+43200000)/86400000); +- if( zFmt[i]=='W' ){ ++ if( cf=='W' ){ + int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ + wd = (int)(((x.iJD+43200000)/86400000)%7); + sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7); +@@ -24471,18 +25588,42 @@ static void strftimeFunc( + 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': { +- i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000); +- sqlite3_str_appendf(&sRes,"%lld",iS); ++ 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': /* Fall thru */ + case 'w': { +- sqlite3_str_appendchar(&sRes, 1, +- (char)(((x.iJD+129600000)/86400000) % 7) + '0'); ++ char c = (char)(((x.iJD+129600000)/86400000) % 7) + '0'; ++ if( c=='0' && cf=='u' ) c = '7'; ++ sqlite3_str_appendchar(&sRes, 1, c); + break; + } + case 'Y': { +@@ -24531,6 +25672,117 @@ static void cdateFunc( + dateFunc(context, 0, 0); + } + ++/* ++** timediff(DATE1, DATE2) ++** ++** Return the amount of time that must be added to DATE2 in order to ++** convert it into DATE2. The time difference format is: ++** ++** +YYYY-MM-DD HH:MM:SS.SSS ++** ++** The initial "+" becomes "-" if DATE1 occurs before DATE2. For ++** date/time values A and B, the following invariant should hold: ++** ++** datetime(A) == (datetime(B, timediff(A,B)) ++** ++** Both DATE arguments must be either a julian day number, or an ++** ISO-8601 string. The unix timestamps are not supported by this ++** routine. ++*/ ++static void timediffFunc( ++ sqlite3_context *context, ++ int NotUsed1, ++ sqlite3_value **argv ++){ ++ char sign; ++ int Y, M; ++ DateTime d1, d2; ++ sqlite3_str sRes; ++ UNUSED_PARAMETER(NotUsed1); ++ if( isDate(context, 1, &argv[0], &d1) ) return; ++ if( isDate(context, 1, &argv[1], &d2) ) return; ++ computeYMD_HMS(&d1); ++ computeYMD_HMS(&d2); ++ if( d1.iJD>=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.iJD d2.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; ++ } ++ d1.validYMD = 0; ++ d1.validHMS = 0; ++ d1.validTZ = 0; ++ 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() + ** +@@ -24605,6 +25857,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ + 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 ), + DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), + DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), + DFUNCTION(current_date, 0, 0, 0, cdateFunc ), +@@ -24727,9 +25980,11 @@ SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *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){ +@@ -24756,7 +26011,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ + /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite + ** is using a regular VFS, it is called after the corresponding + ** transaction has been committed. Injecting a fault at this point +- ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM ++ ** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM + ** but the transaction is committed anyway. + ** + ** The core must call OsFileControl() though, not OsFileControlHint(), +@@ -24844,6 +26099,7 @@ SQLITE_PRIVATE int sqlite3OsOpen( + ** 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; +@@ -25376,7 +26632,7 @@ static void *sqlite3MemMalloc(int nByte){ + ** or sqlite3MemRealloc(). + ** + ** For this low-level routine, we already know that pPrior!=0 since +-** cases where pPrior==0 will have been intecepted and dealt with ++** cases where pPrior==0 will have been intercepted and dealt with + ** by higher-level routines. + */ + static void sqlite3MemFree(void *pPrior){ +@@ -25464,7 +26720,7 @@ static int sqlite3MemInit(void *NotUsed){ + return SQLITE_OK; + } + len = sizeof(cpuCount); +- /* One usually wants to use hw.acctivecpu for MT decisions, but not here */ ++ /* 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 */ +@@ -27159,9 +28415,13 @@ static int memsys5Roundup(int n){ + if( n<=mem5.szAtom ) return mem5.szAtom; + return mem5.szAtom*2; + } +- if( n>0x40000000 ) return 0; ++ if( n>0x10000000 ){ ++ if( n>0x40000000 ) return 0; ++ if( n>0x20000000 ) return 0x40000000; ++ return 0x20000000; ++ } + for(iFullSz=mem5.szAtom*8; iFullSz =n ) return iFullSz/2; ++ if( (iFullSz/2)>=(i64)n ) return iFullSz/2; + return iFullSz; + } + +@@ -27452,7 +28712,7 @@ static void checkMutexFree(sqlite3_mutex *p){ + assert( SQLITE_MUTEX_FAST<2 ); + assert( SQLITE_MUTEX_WARNONCONTENTION<2 ); + +-#if SQLITE_ENABLE_API_ARMOR ++#ifdef SQLITE_ENABLE_API_ARMOR + if( ((CheckMutex*)p)->iType<2 ) + #endif + { +@@ -27927,7 +29187,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ + + /* + ** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields +-** are necessary under two condidtions: (1) Debug builds and (2) using ++** 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) +@@ -28124,7 +29384,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ + */ + static void pthreadMutexFree(sqlite3_mutex *p){ + assert( p->nRef==0 ); +-#if SQLITE_ENABLE_API_ARMOR ++#ifdef SQLITE_ENABLE_API_ARMOR + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) + #endif + { +@@ -28428,7 +29688,7 @@ struct sqlite3_mutex { + CRITICAL_SECTION mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + #ifdef SQLITE_DEBUG +- volatile int nRef; /* Number of enterances */ ++ volatile int nRef; /* Number of entrances */ + volatile DWORD owner; /* Thread holding this mutex */ + volatile LONG trace; /* True to trace changes */ + #endif +@@ -28477,7 +29737,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ + SQLITE_MEMORY_BARRIER; + #elif defined(__GNUC__) + __sync_synchronize(); +-#elif MSVC_VERSION>=1300 ++#elif MSVC_VERSION>=1400 + _ReadWriteBarrier(); + #elif defined(MemoryBarrier) + MemoryBarrier(); +@@ -28961,6 +30221,12 @@ SQLITE_PRIVATE int sqlite3MallocInit(void){ + } + rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); + if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0)); ++ ++ /* Initialize wrapper for memory management.*/ ++ if( rc==SQLITE_OK ) { ++ sqlite3mcInitMemoryMethods(); ++ } ++ + return rc; + } + +@@ -29062,18 +30328,34 @@ static void mallocWithAlarm(int n, void **pp){ + *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>=0x7fffff00 ){ +- /* A memory allocation of a number of bytes which is near the maximum +- ** signed integer value might cause an integer overflow inside of the +- ** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving +- ** 255 bytes of overhead. SQLite itself will never use anything near +- ** this amount. The only way to reach the limit is with sqlite3_malloc() */ ++ if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){ + p = 0; + }else if( sqlite3GlobalConfig.bMemstat ){ + sqlite3_mutex_enter(mem0.mutex); +@@ -29109,7 +30391,7 @@ SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){ + */ + #ifndef SQLITE_OMIT_LOOKASIDE + static int isLookaside(sqlite3 *db, const void *p){ +- return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd); ++ return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd); + } + #else + #define isLookaside(A,B) 0 +@@ -29133,18 +30415,16 @@ static int lookasideMallocSize(sqlite3 *db, const void *p){ + SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, const void *p){ + assert( p!=0 ); + #ifdef SQLITE_DEBUG +- if( db==0 || !isLookaside(db,p) ){ +- if( db==0 ){ +- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); +- assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); +- }else{ +- assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); +- assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); +- } ++ 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.pEnd) ){ ++ 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) ); +@@ -29200,14 +30480,11 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ + assert( db==0 || sqlite3_mutex_held(db->mutex) ); + assert( p!=0 ); + if( db ){ +- if( db->pnBytesFreed ){ +- measureAllocationSize(db, p); +- return; +- } + 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 +@@ -29218,6 +30495,7 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ + #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 +@@ -29226,6 +30504,10 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ + return; + } + } ++ if( db->pnBytesFreed ){ ++ measureAllocationSize(db, p); ++ return; ++ } + } + assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); +@@ -29233,6 +30515,43 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ + 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); +@@ -29532,9 +30851,14 @@ SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ + */ + 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] 0) && sqlite3Isspace(zStart[n-1]) ) n--; ++ while( sqlite3Isspace(zStart[n-1]) ) n--; + return sqlite3DbStrNDup(db, zStart, n); + } + +@@ -29630,7 +30954,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ + if( db->mallocFailed || rc ){ + return apiHandleError(db, rc); + } +- return rc & db->errMask; ++ return 0; + } + + /************** End of malloc.c **********************************************/ +@@ -29742,43 +31066,6 @@ static const et_info fmtinfo[] = { + ** %!S Like %S but prefer the zName over the zAlias + */ + +-/* Floating point constants used for rounding */ +-static const double arRound[] = { +- 5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05, +- 5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10, +-}; +- +-/* +-** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point +-** conversions will work. +-*/ +-#ifndef SQLITE_OMIT_FLOATING_POINT +-/* +-** "*val" is a double such that 0.1 <= *val < 10.0 +-** Return the ascii code for the leading digit of *val, then +-** multiply "*val" by 10.0 to renormalize. +-** +-** Example: +-** input: *val = 3.14159 +-** output: *val = 1.4159 function return = '3' +-** +-** The counter *cnt is incremented each time. After counter exceeds +-** 16 (the number of significant digits in a 64-bit float) '0' is +-** always returned. +-*/ +-static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ +- int digit; +- LONGDOUBLE_TYPE d; +- if( (*cnt)<=0 ) return '0'; +- (*cnt)--; +- digit = (int)*val; +- d = digit; +- digit += '0'; +- *val = (*val - d)*10.0; +- return (char)digit; +-} +-#endif /* SQLITE_OMIT_FLOATING_POINT */ +- + /* + ** Set the StrAccum object to an error mode. + */ +@@ -29870,18 +31157,15 @@ SQLITE_API void sqlite3_str_vappendf( + u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ + char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ + sqlite_uint64 longvalue; /* Value for integer types */ +- LONGDOUBLE_TYPE realvalue; /* Value for real 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 */ +-#ifndef SQLITE_OMIT_FLOATING_POINT +- int exp, e2; /* exponent of real numbers */ +- int nsd; /* Number of significant digits returned */ +- double rounder; /* Used for rounding floating point values */ ++ 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 */ +-#endif ++ + PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ + char buf[etBUFSIZE]; /* Conversion buffer */ + +@@ -30156,73 +31440,66 @@ SQLITE_API void sqlite3_str_vappendf( + break; + case etFLOAT: + case etEXP: +- case etGENERIC: ++ case etGENERIC: { ++ FpDecode s; ++ int iRound; ++ int j; ++ + if( bArgList ){ + realvalue = getDoubleArg(pArgList); + }else{ + realvalue = va_arg(ap,double); + } +-#ifdef SQLITE_OMIT_FLOATING_POINT +- length = 0; +-#else + 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( realvalue<0.0 ){ +- realvalue = -realvalue; +- prefix = '-'; +- }else{ +- prefix = flag_prefix; +- } +- if( xtype==etGENERIC && precision>0 ) precision--; +- testcase( precision>0xfff ); +- idx = precision & 0xfff; +- rounder = arRound[idx%10]; +- while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; } + if( xtype==etFLOAT ){ +- double rx = (double)realvalue; +- sqlite3_uint64 u; +- int ex; +- memcpy(&u, &rx, sizeof(u)); +- ex = -1023 + (int)((u>>52)&0x7ff); +- if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16; +- realvalue += rounder; +- } +- /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ +- exp = 0; +- if( sqlite3IsNaN((double)realvalue) ){ +- bufpt = "NaN"; +- length = 3; +- break; ++ iRound = -precision; ++ }else if( xtype==etGENERIC ){ ++ iRound = precision; ++ }else{ ++ iRound = precision+1; + } +- if( realvalue>0.0 ){ +- LONGDOUBLE_TYPE scale = 1.0; +- while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} +- while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; } +- while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } +- realvalue /= scale; +- while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } +- while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } +- if( exp>350 ){ ++ 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; +- buf[0] = prefix; +- memcpy(buf+(prefix!=0),"Inf",4); +- length = 3+(prefix!=0); ++ if( s.sign=='-' ){ ++ /* no-op */ ++ }else if( flag_prefix ){ ++ buf[0] = flag_prefix; ++ }else{ ++ bufpt++; ++ } ++ length = sqlite3Strlen30(bufpt); + break; + } + } +- bufpt = buf; ++ if( s.sign=='-' ){ ++ prefix = '-'; ++ }else{ ++ prefix = flag_prefix; ++ } ++ ++ exp = s.iDP-1; ++ if( xtype==etGENERIC && precision>0 ) precision--; ++ + /* + ** If the field type is etGENERIC, then convert to either etEXP + ** or etFLOAT, as appropriate. + */ +- if( xtype!=etFLOAT ){ +- realvalue += rounder; +- if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } +- } + if( xtype==etGENERIC ){ + flag_rtz = !flag_alternateform; + if( exp<-4 || exp>precision ){ +@@ -30237,29 +31514,32 @@ SQLITE_API void sqlite3_str_vappendf( + if( xtype==etEXP ){ + e2 = 0; + }else{ +- e2 = exp; ++ 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; +- nsd = 16 + flag_altform2*10; + 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++) = et_getdigit(&realvalue,&nsd); ++ *(bufpt++) = j 1 ) *(bufpt++) = ','; + } + } + /* The decimal point */ +@@ -30268,13 +31548,12 @@ SQLITE_API void sqlite3_str_vappendf( + } + /* "0" digits after the decimal point but before the first + ** significant digit of the number */ +- for(e2++; e2<0; precision--, e2++){ +- assert( precision>0 ); ++ for(e2++; e2<0 && precision>0; precision--, e2++){ + *(bufpt++) = '0'; + } + /* Significant digits after the decimal point */ + while( (precision--)>0 ){ +- *(bufpt++) = et_getdigit(&realvalue,&nsd); ++ *(bufpt++) = j charset]; + if( exp<0 ){ + *(bufpt++) = '-'; exp = -exp; +@@ -30323,8 +31603,8 @@ SQLITE_API void sqlite3_str_vappendf( + while( nPad-- ) bufpt[i++] = '0'; + length = width; + } +-#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ + break; ++ } + case etSIZE: + if( !bArgList ){ + *(va_arg(ap,int*)) = pAccum->nChar; +@@ -30373,13 +31653,26 @@ SQLITE_API void sqlite3_str_vappendf( + } + } + if( precision>1 ){ ++ i64 nPrior = 1; + width -= precision-1; + if( width>1 && !flag_leftjustify ){ + sqlite3_str_appendchar(pAccum, width-1, ' '); + width = 0; + } +- while( precision-- > 1 ){ +- sqlite3_str_append(pAccum, buf, length); ++ 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; +@@ -30607,9 +31900,9 @@ SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExp + ** 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, int N){ ++SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){ + char *zNew; +- assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ ++ assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ + if( p->accError ){ + testcase(p->accError==SQLITE_TOOBIG); + testcase(p->accError==SQLITE_NOMEM); +@@ -30620,8 +31913,7 @@ SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, int N){ + return p->nAlloc - p->nChar - 1; + }else{ + char *zOld = isMalloced(p) ? p->zText : 0; +- i64 szNew = p->nChar; +- szNew += (sqlite3_int64)N + 1; ++ 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 */ +@@ -30651,7 +31943,8 @@ SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, int N){ + return 0; + } + } +- return N; ++ assert( N>=0 && N<=0x7fffffff ); ++ return (int)N; + } + + /* +@@ -30942,12 +32235,22 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li + return zBuf; + } + SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ +- char *z; ++ 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); +- z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); ++ sqlite3_str_vappendf(&acc, zFormat, ap); + va_end(ap); +- return z; ++ zBuf[acc.nChar] = 0; ++ return zBuf; + } + + /* +@@ -31025,6 +32328,75 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ + 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 ****************************************/ + /* +@@ -31247,6 +32619,13 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc) + if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){ + sqlite3_str_appendf(&x, " ON"); + } ++ 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"); ++ + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, i nSrc-1); + n = 0; +@@ -31434,6 +32813,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u + sqlite3TreeViewItem(pView, "FILTER", 1); + sqlite3TreeViewExpr(pView, pWin->pFilter, 0); + sqlite3TreeViewPop(&pView); ++ if( pWin->eFrmType==TK_FILTER ) return; + } + sqlite3TreeViewPush(&pView, more); + if( pWin->zName ){ +@@ -31443,7 +32823,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u + } + if( pWin->zBase ) nElement++; + if( pWin->pOrderBy ) nElement++; +- if( pWin->eFrmType ) nElement++; ++ if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++; + if( pWin->eExclude ) nElement++; + if( pWin->zBase ){ + sqlite3TreeViewPush(&pView, (--nElement)>0); +@@ -31456,7 +32836,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u + if( pWin->pOrderBy ){ + sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); + } +- if( pWin->eFrmType ){ ++ if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){ + char zBuf[30]; + const char *zFrmType = "ROWS"; + if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; +@@ -31516,7 +32896,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + sqlite3TreeViewPop(&pView); + return; + } +- if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){ ++ 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", +@@ -31533,6 +32913,9 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + 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; +@@ -31662,7 +33045,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + }; + assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); + assert( pExpr->pRight ); +- assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE ); ++ assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op ++ == TK_TRUEFALSE ); + x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); + zUniOp = azOp[x]; + break; +@@ -31700,7 +33084,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + assert( ExprUseXList(pExpr) ); + pFarg = pExpr->x.pList; + #ifndef SQLITE_OMIT_WINDOWFUNC +- pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0; ++ pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0; + #else + pWin = 0; + #endif +@@ -31726,7 +33110,13 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); + } + if( pFarg ){ +- sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); ++ 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 ){ +@@ -31735,6 +33125,10 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + #endif + break; + } ++ case TK_ORDER: { ++ sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY"); ++ break; ++ } + #ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: { + assert( ExprUseXSelect(pExpr) ); +@@ -31788,7 +33182,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m + assert( pExpr->x.pList->nExpr==2 ); + pY = pExpr->x.pList->a[0].pExpr; + pZ = pExpr->x.pList->a[1].pExpr; +- sqlite3TreeViewLine(pView, "BETWEEN"); ++ sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs); + sqlite3TreeViewExpr(pView, pX, 1); + sqlite3TreeViewExpr(pView, pY, 1); + sqlite3TreeViewExpr(pView, pZ, 0); +@@ -32344,16 +33738,41 @@ SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc( + ** This structure is the current state of the generator. + */ + static SQLITE_WSD struct sqlite3PrngType { +- unsigned char isInit; /* True if initialized */ +- unsigned char i, j; /* State variables */ +- unsigned char s[256]; /* State variables */ ++ 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 t; + unsigned char *zBuf = pBuf; + + /* The "wsdPrng" macro will resolve to the pseudo-random number generator +@@ -32383,53 +33802,46 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){ + + sqlite3_mutex_enter(mutex); + if( N<=0 || pBuf==0 ){ +- wsdPrng.isInit = 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. The seed value does +- ** not need to contain a lot of randomness since we are not +- ** trying to do secure encryption or anything like that... +- ** +- ** Nothing in this file or anywhere else in SQLite does any kind of +- ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random +- ** number generator) not as an encryption device. ++ ** the first time this routine is called. + */ +- if( !wsdPrng.isInit ){ ++ if( wsdPrng.s[0]==0 ){ + sqlite3_vfs *pVfs = sqlite3_vfs_find(0); +- int i; +- char k[256]; +- wsdPrng.j = 0; +- wsdPrng.i = 0; ++ static const u32 chacha20_init[] = { ++ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 ++ }; ++ memcpy(&wsdPrng.s[0], chacha20_init, 16); + if( NEVER(pVfs==0) ){ +- memset(k, 0, sizeof(k)); ++ memset(&wsdPrng.s[4], 0, 44); + }else{ +- sqlite3OsRandomness(pVfs, 256, k); +- } +- for(i=0; i<256; i++){ +- wsdPrng.s[i] = (u8)i; ++ sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]); + } +- for(i=0; i<256; i++){ +- wsdPrng.j += wsdPrng.s[i] + k[i]; +- t = wsdPrng.s[wsdPrng.j]; +- wsdPrng.s[wsdPrng.j] = wsdPrng.s[i]; +- wsdPrng.s[i] = t; +- } +- wsdPrng.isInit = 1; ++ wsdPrng.s[15] = wsdPrng.s[12]; ++ wsdPrng.s[12] = 0; ++ wsdPrng.n = 0; + } + + assert( N>0 ); +- do{ +- wsdPrng.i++; +- t = wsdPrng.s[wsdPrng.i]; +- wsdPrng.j += t; +- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j]; +- wsdPrng.s[wsdPrng.j] = t; +- t += wsdPrng.s[wsdPrng.i]; +- *(zBuf++) = wsdPrng.s[t]; +- }while( --N ); ++ 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); + } + +@@ -32905,7 +34317,38 @@ SQLITE_PRIVATE u32 sqlite3Utf8Read( + 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( i nDb; 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); +@@ -33454,6 +34914,30 @@ SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *z + } + } + ++/* ++** 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. + ** +@@ -33645,43 +35129,40 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ + return h; + } + +-/* +-** Compute 10 to the E-th power. Examples: E==1 results in 10. +-** E==2 results in 100. E==50 results in 1.0e50. ++/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) + ** +-** This routine only works for values of E between 1 and 341. ++** Reference: ++** T. J. Dekker, "A Floating-Point Technique for Extending the ++** Available Precision". 1971-07-26. + */ +-static LONGDOUBLE_TYPE sqlite3Pow10(int E){ +-#if defined(_MSC_VER) +- static const LONGDOUBLE_TYPE x[] = { +- 1.0e+001L, +- 1.0e+002L, +- 1.0e+004L, +- 1.0e+008L, +- 1.0e+016L, +- 1.0e+032L, +- 1.0e+064L, +- 1.0e+128L, +- 1.0e+256L +- }; +- LONGDOUBLE_TYPE r = 1.0; +- int i; +- assert( E>=0 && E<=307 ); +- for(i=0; E!=0; i++, E >>=1){ +- if( E & 1 ) r *= x[i]; +- } +- return r; +-#else +- LONGDOUBLE_TYPE x = 10.0; +- LONGDOUBLE_TYPE r = 1.0; +- while(1){ +- if( E & 1 ) r *= x; +- E >>= 1; +- if( E==0 ) break; +- x *= x; +- } +- return r; +-#endif ++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; + } + + /* +@@ -33722,12 +35203,11 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en + const char *zEnd; + /* sign * significand * (10 ^ (esign * exponent)) */ + int sign = 1; /* sign of significand */ +- i64 s = 0; /* 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 */ +- double result; + int nDigit = 0; /* Number of digits processed */ + int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ + +@@ -33767,7 +35247,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en + while( z =((LARGEST_INT64-9)/10) ){ ++ if( s>=((LARGEST_UINT64-9)/10) ){ + /* skip non-significant significand digits + ** (increase exponent by d to shift decimal left) */ + while( z 0 ){ /*OPTIMIZATION-IF-TRUE*/ +- if( esign>0 ){ +- if( s>=(LARGEST_INT64/10) ) break; /*OPTIMIZATION-IF-FALSE*/ +- s *= 10; +- }else{ +- if( s%10!=0 ) break; /*OPTIMIZATION-IF-FALSE*/ +- s /= 10; +- } +- e--; +- } ++ /* adjust exponent by d, and update sign */ ++ e = (e*esign) + d; + +- /* adjust the sign of significand */ +- s = sign<0 ? -s : s; ++ /* Try to adjust the exponent to make it smaller */ ++ while( e>0 && s<(LARGEST_UINT64/10) ){ ++ s *= 10; ++ e--; ++ } ++ while( e<0 && (s%10)==0 ){ ++ s /= 10; ++ e++; ++ } + +- if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ +- result = (double)s; ++ if( e==0 ){ ++ *pResult = s; ++ }else if( sqlite3Config.bUseLongDouble ){ ++ LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s; ++ if( e>0 ){ ++ while( e>=100 ){ e-=100; r *= 1.0e+100L; } ++ while( e>=10 ){ e-=10; r *= 1.0e+10L; } ++ while( e>=1 ){ e-=1; r *= 1.0e+01L; } + }else{ +- /* attempt to handle extremely small/large numbers better */ +- if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ +- if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ +- LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); +- if( esign<0 ){ +- result = s / scale; +- result /= 1.0e+308; +- }else{ +- result = s * scale; +- result *= 1.0e+308; +- } +- }else{ assert( e>=342 ); +- if( esign<0 ){ +- result = 0.0*s; +- }else{ ++ while( e<=-100 ){ e+=100; r *= 1.0e-100L; } ++ while( e<=-10 ){ e+=10; r *= 1.0e-10L; } ++ while( e<=-1 ){ e+=1; r *= 1.0e-01L; } ++ } ++ assert( r>=0.0 ); ++ if( r>+1.7976931348623157081452742373e+308L ){ + #ifdef INFINITY +- result = INFINITY*s; ++ *pResult = +INFINITY; + #else +- result = 1e308*1e308*s; /* Infinity */ ++ *pResult = 1.0e308*10.0; + #endif +- } +- } +- }else{ +- LONGDOUBLE_TYPE scale = sqlite3Pow10(e); +- if( esign<0 ){ +- result = s / scale; +- }else{ +- result = s * scale; +- } ++ }else{ ++ *pResult = (double)r; ++ } ++ }else{ ++ double rr[2]; ++ u64 s2; ++ rr[0] = (double)s; ++ s2 = (u64)rr[0]; ++ rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); ++ 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) ); + +- /* store the result */ +- *pResult = result; +- +- /* return true if number and no extra non-whitespace chracters after */ ++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 ){ +@@ -33911,11 +35401,14 @@ do_atof_calc: + #endif + + /* +-** Render an signed 64-bit integer as text. Store the result in zOut[]. ++** 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 void sqlite3Int64ToText(i64 v, char *zOut){ ++SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){ + int i; + u64 x; + char zTemp[22]; +@@ -33926,12 +35419,15 @@ SQLITE_PRIVATE void sqlite3Int64ToText(i64 v, char *zOut){ + } + i = sizeof(zTemp)-2; + zTemp[sizeof(zTemp)-1] = 0; +- do{ +- zTemp[i--] = (x%10) + '0'; ++ while( 1 /*exit-by-break*/ ){ ++ zTemp[i] = (x%10) + '0'; + x = x/10; +- }while( x ); +- if( v<0 ) zTemp[i--] = '-'; +- memcpy(zOut, &zTemp[i+1], sizeof(zTemp)-1-i); ++ if( x==0 ) break; ++ i--; ++ }; ++ if( v<0 ) zTemp[--i] = '-'; ++ memcpy(zOut, &zTemp[i], sizeof(zTemp)-i); ++ return sizeof(zTemp)-1-i; + } + + /* +@@ -34024,7 +35520,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc + /* 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 appaise the undefined-behavior pharisees. */ ++ ** them, but we must appease the undefined-behavior pharisees. */ + *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; + }else if( neg ){ + *pNum = -(i64)u; +@@ -34096,11 +35592,15 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ + u = u*16 + sqlite3HexToInt(z[k]); + } + memcpy(pOut, &u, 8); +- return (z[k]==0 && k-i<=16) ? 0 : 2; ++ if( k-i>16 ) return 2; ++ if( z[k]!=0 ) return 1; ++ return 0; + }else + #endif /* SQLITE_OMIT_HEX_INTEGER */ + { +- return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); ++ int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789")); ++ if( z[n] ) n++; ++ return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8); + } + } + +@@ -34132,7 +35632,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){ + u32 u = 0; + zNum += 2; + while( zNum[0]=='0' ) zNum++; +- for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){ ++ for(i=0; i<8 && sqlite3Isxdigit(zNum[i]); i++){ + u = u*16 + sqlite3HexToInt(zNum[i]); + } + if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ +@@ -34179,6 +35679,153 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ + return x; + } + ++/* ++** Decode a floating-point value into an approximate decimal ++** representation. ++** ++** Round the decimal representation to n significant digits if ++** n is positive. Or round to -n signficant digits after the ++** decimal point if n is negative. No rounding is performed if ++** n is zero. ++** ++** 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; ++ p->isSpecial = 0; ++ p->z = p->zBuf; ++ ++ /* 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. ++ */ ++ if( sqlite3Config.bUseLongDouble ){ ++ LONGDOUBLE_TYPE rr = r; ++ if( rr>=1.0e+19 ){ ++ while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; } ++ while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; } ++ while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; } ++ }else{ ++ while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; } ++ while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; } ++ while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; } ++ } ++ v = (u64)rr; ++ }else{ ++ /* If high-precision floating point is not available using "long double", ++ ** then 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))); ++ */ ++ double rr[2]; ++ 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 && i zBuf)-1 ); ++ p->n = sizeof(p->zBuf) - 1 - i; ++ assert( p->n>0 ); ++ assert( p->n zBuf) ); ++ 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 && (iRound n || 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) ); ++ while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; } ++} ++ + /* + ** Try to convert z into an unsigned 32-bit integer. Return true on + ** success and false if there is an error. +@@ -34442,121 +36089,32 @@ SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){ + ** this function assumes the single-byte case has already been handled. + */ + SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){ +- u32 a,b; ++ u64 v64; ++ u8 n; + +- /* The 1-byte case. Overwhelmingly the most common. Handled inline +- ** by the getVarin32() macro */ +- a = *p; +- /* a: p0 (unmasked) */ +-#ifndef getVarint32 +- if (!(a&0x80)) +- { +- /* Values between 0 and 127 */ +- *v = a; +- return 1; +- } +-#endif ++ /* Assume that the single-byte case has already been handled by ++ ** the getVarint32() macro */ ++ assert( (p[0] & 0x80)!=0 ); + +- /* The 2-byte case */ +- p++; +- b = *p; +- /* b: p1 (unmasked) */ +- if (!(b&0x80)) +- { +- /* Values between 128 and 16383 */ +- a &= 0x7f; +- a = a<<7; +- *v = a | b; ++ if( (p[1] & 0x80)==0 ){ ++ /* This is the two-byte case */ ++ *v = ((p[0]&0x7f)<<7) | p[1]; + return 2; + } +- +- /* The 3-byte case */ +- p++; +- a = a<<14; +- a |= *p; +- /* a: p0<<14 | p2 (unmasked) */ +- if (!(a&0x80)) +- { +- /* Values between 16384 and 2097151 */ +- a &= (0x7f<<14)|(0x7f); +- b &= 0x7f; +- b = b<<7; +- *v = a | b; ++ if( (p[2] & 0x80)==0 ){ ++ /* This is the three-byte case */ ++ *v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2]; + return 3; + } +- +- /* A 32-bit varint is used to store size information in btrees. +- ** Objects are rarely larger than 2MiB limit of a 3-byte varint. +- ** A 3-byte varint is sufficient, for example, to record the size +- ** of a 1048569-byte BLOB or string. +- ** +- ** We only unroll the first 1-, 2-, and 3- byte cases. The very +- ** rare larger cases can be handled by the slower 64-bit varint +- ** routine. +- */ +-#if 1 +- { +- u64 v64; +- u8 n; +- +- n = sqlite3GetVarint(p-2, &v64); +- assert( n>3 && n<=9 ); +- if( (v64 & SQLITE_MAX_U32)!=v64 ){ +- *v = 0xffffffff; +- }else{ +- *v = (u32)v64; +- } +- return n; +- } +- +-#else +- /* For following code (kept for historical record only) shows an +- ** unrolling for the 3- and 4-byte varint cases. This code is +- ** slightly faster, but it is also larger and much harder to test. +- */ +- p++; +- b = b<<14; +- b |= *p; +- /* b: p1<<14 | p3 (unmasked) */ +- if (!(b&0x80)) +- { +- /* Values between 2097152 and 268435455 */ +- b &= (0x7f<<14)|(0x7f); +- a &= (0x7f<<14)|(0x7f); +- a = a<<7; +- *v = a | b; +- return 4; +- } +- +- p++; +- a = a<<14; +- a |= *p; +- /* a: p0<<28 | p2<<14 | p4 (unmasked) */ +- if (!(a&0x80)) +- { +- /* Values between 268435456 and 34359738367 */ +- a &= SLOT_4_2_0; +- b &= SLOT_4_2_0; +- b = b<<7; +- *v = a | b; +- return 5; +- } +- +- /* We can only reach this point when reading a corrupt database +- ** file. In that case we are not in any hurry. Use the (relatively +- ** slow) general-purpose sqlite3GetVarint() routine to extract the +- ** value. */ +- { +- u64 v64; +- u8 n; +- +- p -= 4; +- n = sqlite3GetVarint(p, &v64); +- assert( n>5 && n<=9 ); ++ /* 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; + } +-#endif ++ return n; + } + + /* +@@ -34707,7 +36265,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ + } + + /* +-** Attempt to add, substract, or multiply the 64-bit signed value iB against ++** 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. +@@ -34993,6 +36551,104 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam + return 0; + } + ++/* ++** 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 util.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 util.c ***********************/ ++#endif ++ + /************** End of util.c ************************************************/ + /************** Begin file hash.c ********************************************/ + /* +@@ -35094,7 +36750,7 @@ static void insertElement( + } + + +-/* Resize the hash table so that it cantains "new_size" buckets. ++/* 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. +@@ -35163,12 +36819,13 @@ static HashElem *findElementWithHash( + count = pH->count; + } + if( pHash ) *pHash = h; +- while( count-- ){ ++ while( count ){ + assert( elem!=0 ); + if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ + return elem; + } + elem = elem->next; ++ count--; + } + return &nullElement; + } +@@ -35287,48 +36944,48 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + /* 5 */ "Vacuum" OpHelp(""), + /* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), + /* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"), +- /* 8 */ "Goto" OpHelp(""), +- /* 9 */ "Gosub" OpHelp(""), +- /* 10 */ "InitCoroutine" OpHelp(""), +- /* 11 */ "Yield" OpHelp(""), +- /* 12 */ "MustBeInt" OpHelp(""), +- /* 13 */ "Jump" OpHelp(""), +- /* 14 */ "Once" OpHelp(""), +- /* 15 */ "If" OpHelp(""), +- /* 16 */ "IfNot" OpHelp(""), +- /* 17 */ "IsNullOrType" OpHelp("if typeof(r[P1]) IN (P3,5) goto P2"), +- /* 18 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), ++ /* 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 */ "SeekLT" OpHelp("key=r[P3@P4]"), +- /* 21 */ "SeekLE" OpHelp("key=r[P3@P4]"), +- /* 22 */ "SeekGE" OpHelp("key=r[P3@P4]"), +- /* 23 */ "SeekGT" OpHelp("key=r[P3@P4]"), +- /* 24 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"), +- /* 25 */ "IfNoHope" OpHelp("key=r[P3@P4]"), +- /* 26 */ "NoConflict" OpHelp("key=r[P3@P4]"), +- /* 27 */ "NotFound" OpHelp("key=r[P3@P4]"), +- /* 28 */ "Found" OpHelp("key=r[P3@P4]"), +- /* 29 */ "SeekRowid" OpHelp("intkey=r[P3]"), +- /* 30 */ "NotExists" OpHelp("intkey=r[P3]"), +- /* 31 */ "Last" OpHelp(""), +- /* 32 */ "IfSmaller" OpHelp(""), +- /* 33 */ "SorterSort" OpHelp(""), +- /* 34 */ "Sort" OpHelp(""), +- /* 35 */ "Rewind" OpHelp(""), +- /* 36 */ "SorterNext" OpHelp(""), +- /* 37 */ "Prev" OpHelp(""), +- /* 38 */ "Next" OpHelp(""), +- /* 39 */ "IdxLE" OpHelp("key=r[P3@P4]"), +- /* 40 */ "IdxGT" OpHelp("key=r[P3@P4]"), +- /* 41 */ "IdxLT" OpHelp("key=r[P3@P4]"), +- /* 42 */ "IdxGE" OpHelp("key=r[P3@P4]"), ++ /* 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 */ "IfSmaller" 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 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), +- /* 46 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), +- /* 47 */ "Program" OpHelp(""), +- /* 48 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), +- /* 49 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), ++ /* 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 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), + /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), + /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), +@@ -35338,12 +36995,12 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + /* 56 */ "Lt" OpHelp("IF r[P3] =r[P1]"), + /* 58 */ "ElseEq" OpHelp(""), +- /* 59 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), +- /* 60 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), +- /* 61 */ "IncrVacuum" OpHelp(""), +- /* 62 */ "VNext" OpHelp(""), +- /* 63 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"), +- /* 64 */ "Init" OpHelp("Start at P2"), ++ /* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), ++ /* 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(""), +@@ -35453,25 +37110,1010 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + /* 171 */ "VCreate" OpHelp(""), + /* 172 */ "VDestroy" OpHelp(""), + /* 173 */ "VOpen" OpHelp(""), +- /* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), +- /* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), +- /* 176 */ "VRename" OpHelp(""), +- /* 177 */ "Pagecount" OpHelp(""), +- /* 178 */ "MaxPgcnt" OpHelp(""), +- /* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), +- /* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), +- /* 181 */ "Trace" OpHelp(""), +- /* 182 */ "CursorHint" OpHelp(""), +- /* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), +- /* 184 */ "Noop" OpHelp(""), +- /* 185 */ "Explain" OpHelp(""), +- /* 186 */ "Abortable" OpHelp(""), ++ /* 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+k 0 ){ ++ 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( n nJrnl ){ ++ 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( n zClass, iAmt, iOfst)); ++ if( iEnd>=0x10000000 ) return SQLITE_FULL; ++ if( pFile->aJrnl==0 || pFile->nJrnl aJrnl, iEnd); ++ if( aNew==0 ){ ++ return SQLITE_IOERR_NOMEM; ++ } ++ pFile->aJrnl = aNew; ++ if( pFile->nJrnl aJrnl+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 +@@ -35497,7 +38139,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + ** 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 labeled. ++** in the correct division and should be clearly labelled. + ** + ** The layout of divisions is as follows: + ** +@@ -35547,7 +38189,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + #endif + + /* Use pread() and pwrite() if they are available */ +-#if defined(__APPLE__) ++#if defined(__APPLE__) || defined(__linux__) + # define HAVE_PREAD 1 + # define HAVE_PWRITE 1 + #endif +@@ -35562,15 +38204,16 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + /* + ** standard include files. + */ +-#include +-#include ++#include /* amalgamator: keep */ ++#include /* amalgamator: keep */ + #include + #include +-#include ++#include /* amalgamator: keep */ + /* #include */ +-#include ++#include /* amalgamator: keep */ + #include +-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 ++#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \ ++ && !defined(SQLITE_WASI) + # include + #endif + +@@ -35651,16 +38294,57 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ + /* + ** Maximum supported path-length. + */ ++#if SQLITE3MC_MAX_PATHNAME > 512 ++#define MAX_PATHNAME SQLITE3MC_MAX_PATHNAME ++#else + #define MAX_PATHNAME 512 ++#endif + + /* + ** 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 ++# 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() ++# define osGetpid(X) (pid_t)getpid() ++#endif + + /* + ** Only set the lastErrno if the error code is a real error and not +@@ -35932,7 +38616,11 @@ static struct unix_syscall { + #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 +@@ -35968,14 +38656,16 @@ static struct unix_syscall { + #endif + #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) + +-#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 ++#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 ++#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 }, +@@ -36040,7 +38730,7 @@ static int robustFchown(int fd, uid_t uid, gid_t gid){ + + /* + ** This is the xSetSystemCall() method of sqlite3_vfs for all of the +-** "unix" VFSes. Return SQLITE_OK opon successfully updating 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. + */ +@@ -36161,6 +38851,9 @@ static int robust_open(const char *z, int f, mode_t m){ + break; + } + if( fd>=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); +@@ -36559,7 +39252,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ + ** 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 tha inode. ++** 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. +@@ -36573,7 +39266,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){ + ** 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 appliation uses the newer Native Posix Thread Library (NPTL) ++** 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 +@@ -36775,7 +39468,7 @@ static void storeLastErrno(unixFile *pFile, int error){ + } + + /* +-** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. ++** Close all file descriptors accumulated in the unixInodeInfo->pUnused list. + */ + static void closePendingFds(unixFile *pFile){ + unixInodeInfo *pInode = pFile->pInode; +@@ -37123,7 +39816,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ + ** + ** UNLOCKED -> SHARED + ** SHARED -> RESERVED +-** SHARED -> (PENDING) -> EXCLUSIVE ++** SHARED -> EXCLUSIVE + ** RESERVED -> (PENDING) -> EXCLUSIVE + ** PENDING -> EXCLUSIVE + ** +@@ -37138,7 +39831,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + ** 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 indentify the 'pending byte' and the 'reserved ++ ** 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. + ** +@@ -37146,7 +39839,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + ** 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 Widnows95 lacks a shared-lock capability. So on Windows95, a ++ ** 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 +@@ -37156,19 +39849,20 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + ** A RESERVED lock is implemented by grabbing a write-lock on the + ** 'reserved byte'. + ** +- ** A process may only obtain a PENDING lock after it has obtained a +- ** SHARED lock. 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. A process +- ** does not have to obtain a RESERVED lock on the way to a PENDING lock. +- ** This property is used by the algorithm for rolling back a journal file +- ** after a crash. ++ ** 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. + ** +- ** An EXCLUSIVE lock, obtained after a PENDING lock is held, 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; +@@ -37194,7 +39888,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + + /* 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 pendig 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 ); +@@ -37239,7 +39933,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + lock.l_len = 1L; + lock.l_whence = SEEK_SET; + if( eFileLock==SHARED_LOCK +- || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock eFileLock==RESERVED_LOCK) + ){ + lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK); + lock.l_start = PENDING_BYTE; +@@ -37250,6 +39944,9 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + storeLastErrno(pFile, tErrno); + } + goto end_lock; ++ }else if( eFileLock==EXCLUSIVE_LOCK ){ ++ pFile->eFileLock = PENDING_LOCK; ++ pInode->eFileLock = PENDING_LOCK; + } + } + +@@ -37337,13 +40034,9 @@ static int unixLock(sqlite3_file *id, int eFileLock){ + } + #endif + +- + if( rc==SQLITE_OK ){ + pFile->eFileLock = eFileLock; + pInode->eFileLock = eFileLock; +- }else if( eFileLock==EXCLUSIVE_LOCK ){ +- pFile->eFileLock = PENDING_LOCK; +- pInode->eFileLock = PENDING_LOCK; + } + + end_lock: +@@ -38413,7 +41106,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ + + /* 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 pendig 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 ); +@@ -38529,7 +41222,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ + if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + + pInode->sharedByte, 1, 0)) ){ + int failed2 = SQLITE_OK; +- /* now attemmpt to get the exclusive lock range */ ++ /* 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, +@@ -38578,9 +41271,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { + unixInodeInfo *pInode; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + int skipShared = 0; +-#ifdef SQLITE_TEST +- int h = pFile->h; +-#endif + + assert( pFile ); + OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, +@@ -38596,9 +41286,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { + assert( pInode->nShared!=0 ); + if( pFile->eFileLock>SHARED_LOCK ){ + assert( pInode->eFileLock==pFile->eFileLock ); +- SimulateIOErrorBenign(1); +- SimulateIOError( h=(-1) ) +- SimulateIOErrorBenign(0); + + #ifdef SQLITE_DEBUG + /* When reducing a lock such that other processes can start +@@ -38647,9 +41334,6 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { + unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte; + pInode->nShared--; + if( pInode->nShared==0 ){ +- SimulateIOErrorBenign(1); +- SimulateIOError( h=(-1) ) +- SimulateIOErrorBenign(0); + if( !skipShared ){ + rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); + } +@@ -38750,12 +41434,6 @@ static int nfsUnlock(sqlite3_file *id, int eFileLock){ + ** Seek to the offset passed as the second argument, then read cnt + ** bytes into pBuf. Return the number of bytes actually read. + ** +-** NB: If you define USE_PREAD or USE_PREAD64, then it might also +-** be necessary to define _XOPEN_SOURCE to be 500. This varies from +-** one system to another. Since SQLite does not define USE_PREAD +-** in any form by default, we will not attempt to define _XOPEN_SOURCE. +-** See tickets #2741 and #2681. +-** + ** To avoid stomping the errno value on a failed read the lastErrno value + ** is set before returning. + */ +@@ -38830,7 +41508,7 @@ static int unixRead( + #endif + + #if SQLITE_MAX_MMAP_SIZE>0 +- /* Deal with as much of this read request as possible by transfering ++ /* Deal with as much of this read request as possible by transferring + ** data from the memory mapping using memcpy(). */ + if( offset mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ +@@ -38982,7 +41660,7 @@ static int unixWrite( + #endif + + #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 +- /* Deal with as much of this write request as possible by transfering ++ /* Deal with as much of this write request as possible by transferring + ** data from the memory mapping using memcpy(). */ + if( offset mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ +@@ -39104,7 +41782,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ + /* 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 +- ** coverate testing. ++ ** coverage testing. + */ + #ifdef SQLITE_NO_SYNC + { +@@ -39497,7 +42175,13 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + #ifdef SQLITE_ENABLE_SETLK_TIMEOUT + case SQLITE_FCNTL_LOCK_TIMEOUT: { + int iOld = pFile->iBusyTimeout; ++#if SQLITE_ENABLE_SETLK_TIMEOUT==1 + pFile->iBusyTimeout = *(int*)pArg; ++#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; + } +@@ -39750,6 +42434,25 @@ static int unixGetpagesize(void){ + ** 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 */ +@@ -39763,10 +42466,11 @@ struct unixShmNode { + 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 exclMask; /* Mask of exclusive locks held */ +- u8 sharedMask; /* Mask of shared locks held */ + u8 nextShmId; /* Next available unixShm.id value */ + #endif + }; +@@ -39849,16 +42553,35 @@ static int unixShmSystemLock( + struct flock f; /* The posix advisory locking structure */ + int rc = SQLITE_OK; /* Result code form fcntl() */ + +- /* Access to the unixShmNode object is serialized by the caller */ + pShmNode = pFile->pInode->pShmNode; +- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); +- assert( pShmNode->nRef>0 || unixMutexHeld() ); ++ ++ /* 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; ii aMutex[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; +@@ -39869,7 +42592,7 @@ static int unixShmSystemLock( + f.l_len = n; + res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); + if( res==-1 ){ +-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1 + rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY); + #else + rc = SQLITE_BUSY; +@@ -39877,39 +42600,28 @@ static int unixShmSystemLock( + } + } + +- /* Update the global lock state and do debug tracing */ ++ /* Do debug tracing */ + #ifdef SQLITE_DEBUG +- { u16 mask; + OSTRACE(("SHM-LOCK ")); +- mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1< exclMask &= ~mask; +- pShmNode->sharedMask &= ~mask; ++ OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1)); + }else if( lockType==F_RDLCK ){ +- OSTRACE(("read-lock %d ok", ofst)); +- pShmNode->exclMask &= ~mask; +- pShmNode->sharedMask |= mask; ++ OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1)); + }else{ + assert( lockType==F_WRLCK ); +- OSTRACE(("write-lock %d ok", ofst)); +- pShmNode->exclMask |= mask; +- pShmNode->sharedMask &= ~mask; ++ OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1)); + } + }else{ + if( lockType==F_UNLCK ){ +- OSTRACE(("unlock %d failed", ofst)); ++ OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1)); + }else if( lockType==F_RDLCK ){ +- OSTRACE(("read-lock failed")); ++ OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1)); + }else{ + assert( lockType==F_WRLCK ); +- OSTRACE(("write-lock %d failed", ofst)); ++ OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1)); + } + } +- OSTRACE((" - afterwards %03x,%03x\n", +- pShmNode->sharedMask, pShmNode->exclMask)); +- } + #endif + + return rc; +@@ -39946,6 +42658,11 @@ static void unixShmPurge(unixFile *pFd){ + int i; + assert( p->pInode==pFd->pInode ); + sqlite3_mutex_free(p->pShmMutex); ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ for(i=0; i aMutex[i]); ++ } ++#endif + for(i=0; i nRegion; i+=nShmPerMap){ + if( p->hShm>=0 ){ + osMunmap(p->apRegion[i], p->szRegion); +@@ -40005,7 +42722,20 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){ + 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 +@@ -40126,6 +42856,18 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ + rc = SQLITE_NOMEM_BKPT; + goto shm_open_err; + } ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ { ++ int ii; ++ for(ii=0; ii aMutex[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 ){ +@@ -40347,9 +43089,11 @@ shmpage_out: + */ + #ifdef SQLITE_DEBUG + static int assertLockingArrayOk(unixShmNode *pShmNode){ ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ return 1; ++#else + unixShm *pX; + int aLock[SQLITE_SHM_NLOCK]; +- assert( sqlite3_mutex_held(pShmNode->pShmMutex) ); + + memset(aLock, 0, sizeof(aLock)); + for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ +@@ -40367,13 +43111,14 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){ + + 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 ++** 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. +@@ -40388,7 +43133,7 @@ static int unixShmLock( + unixShm *p; /* The shared memory being locked */ + unixShmNode *pShmNode; /* The underlying file iNode */ + int rc = SQLITE_OK; /* Result code */ +- u16 mask; /* Mask of locks to take or release */ ++ u16 mask = (1<<(ofst+n)) - (1< pShm; +@@ -40423,88 +43168,151 @@ static int unixShmLock( + ** It is not permitted to block on the RECOVER lock. + */ + #ifdef SQLITE_ENABLE_SETLK_TIMEOUT +- assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( +- (ofst!=2) /* not RECOVER */ +- && (ofst!=1 || (p->exclMask|p->sharedMask)==0) +- && (ofst!=0 || (p->exclMask|p->sharedMask)<3) +- && (ofst<3 || (p->exclMask|p->sharedMask)<(1< exclMask|p->sharedMask); ++ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( ++ (ofst!=2) /* not RECOVER */ ++ && (ofst!=1 || lockMask==0 || lockMask==2) ++ && (ofst!=0 || lockMask<3) ++ && (ofst<3 || lockMask<(1< 1 || mask==(1< pShmMutex); +- assert( assertLockingArrayOk(pShmNode) ); +- if( flags & SQLITE_SHM_UNLOCK ){ +- if( (p->exclMask|p->sharedMask) & mask ){ +- int ii; +- int bUnlock = 1; ++ /* Check if there is any work to do. There are three cases: ++ ** ++ ** a) An unlock operation where there are locks to unlock, ++ ** b) An shared lock where the requested lock is not already held ++ ** c) An exclusive lock where the requested lock is not already held ++ ** ++ ** The SQLite core never requests an exclusive lock that it already holds. ++ ** This is assert()ed below. ++ */ ++ assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK) ++ || 0==(p->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)) ++ ){ + +- for(ii=ofst; ii ((p->sharedMask & (1< aMutex[iMutex]); ++ if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes; ++ }else{ ++ sqlite3_mutex_enter(pShmNode->aMutex[iMutex]); + } ++ } ++#else ++ sqlite3_mutex_enter(pShmNode->pShmMutex); ++#endif + +- if( bUnlock ){ +- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); +- if( rc==SQLITE_OK ){ +- memset(&aLock[ofst], 0, sizeof(int)*n); ++ 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; ++ } + } +- }else if( ALWAYS(p->sharedMask & (1< 1 ); +- aLock[ofst]--; +- } + +- /* Undo the local locks */ +- if( rc==SQLITE_OK ){ +- p->exclMask &= ~mask; +- p->sharedMask &= ~mask; +- } +- } +- }else if( flags & SQLITE_SHM_SHARED ){ +- assert( n==1 ); +- assert( (p->exclMask & (1< sharedMask & mask)==0 ){ +- if( aLock[ofst]<0 ){ +- rc = SQLITE_BUSY; +- }else if( aLock[ofst]==0 ){ +- rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); +- } ++ 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. */ + +- /* Get the local shared locks */ +- if( rc==SQLITE_OK ){ +- p->sharedMask |= mask; +- aLock[ofst]++; +- } +- } +- }else{ +- /* Make sure no sibling connections hold locks that will block this +- ** lock. If any do, return SQLITE_BUSY right away. */ +- int ii; +- for(ii=ofst; ii sharedMask & mask)==0 ); +- if( ALWAYS((p->exclMask & (1< 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 ); +- p->exclMask |= mask; ++ 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; ii exclMask |= mask; ++ for(ii=ofst; ii =ofst; iMutex--){ ++ sqlite3_mutex_leave(pShmNode->aMutex[iMutex]); + } ++#else ++ sqlite3_mutex_leave(pShmNode->pShmMutex); ++#endif + } +- assert( assertLockingArrayOk(pShmNode) ); +- sqlite3_mutex_leave(pShmNode->pShmMutex); ++ + OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", + p->id, osGetpid(0), p->sharedMask, p->exclMask)); + return rc; +@@ -40754,11 +43562,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **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 = unixMapfile(pFd, -1); + if( rc!=SQLITE_OK ) return rc; + } +- if( pFd->mmapSize >= iOff+nAmt ){ ++ if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ + *pp = &((u8 *)pFd->pMapRegion)[iOff]; + pFd->nFetchOut++; + } +@@ -41934,12 +44747,10 @@ static void appendOnePathElement( + if( zName[0]=='.' ){ + if( nName==1 ) return; + if( zName[1]=='.' && nName==2 ){ +- if( pPath->nUsed<=1 ){ +- pPath->rc = SQLITE_ERROR; +- return; ++ if( pPath->nUsed>1 ){ ++ assert( pPath->zOut[0]=='/' ); ++ while( pPath->zOut[--pPath->nUsed]!='/' ){} + } +- assert( pPath->zOut[0]=='/' ); +- while( pPath->zOut[--pPath->nUsed]!='/' ){} + return; + } + } +@@ -42151,12 +44962,17 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ + ** than the argument. + */ + static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){ +-#if OS_VXWORKS ++#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 conjuction 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 +@@ -43533,8 +46349,16 @@ SQLITE_API int sqlite3_os_init(void){ + + /* 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 +@@ -44738,7 +47562,7 @@ static struct win_syscall { + + /* + ** This is the xSetSystemCall() method of sqlite3_vfs for all of the +-** "win32" VFSes. Return SQLITE_OK opon successfully updating 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. + */ +@@ -46318,7 +49142,7 @@ static int winRead( + pFile->h, pBuf, amt, offset, pFile->locktype)); + + #if SQLITE_MAX_MMAP_SIZE>0 +- /* Deal with as much of this read request as possible by transfering ++ /* Deal with as much of this read request as possible by transferring + ** data from the memory mapping using memcpy(). */ + if( offset mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ +@@ -46396,7 +49220,7 @@ static int winWrite( + 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 transfering ++ /* Deal with as much of this write request as possible by transferring + ** data from the memory mapping using memcpy(). */ + if( offset mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ +@@ -46506,7 +49330,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ + ** 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 trancations a no-op if there are pending reads. We ++ ** 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; +@@ -46565,7 +49389,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ + #ifdef SQLITE_TEST + /* + ** Count the number of fullsyncs and normal syncs. This is used to test +-** that syncs and fullsyncs are occuring at the right times. ++** that syncs and fullsyncs are occurring at the right times. + */ + SQLITE_API int sqlite3_sync_count = 0; + SQLITE_API int sqlite3_fullsync_count = 0; +@@ -46922,7 +49746,7 @@ static int winLock(sqlite3_file *id, int locktype){ + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + assert( pFile->locktype>=SHARED_LOCK ); +- res = winUnlockReadLock(pFile); ++ (void)winUnlockReadLock(pFile); + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, + SHARED_SIZE, 0); + if( res ){ +@@ -48100,6 +50924,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **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 ){ +@@ -48108,7 +50937,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ + return rc; + } + } +- if( pFd->mmapSize >= iOff+nAmt ){ ++ if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ + assert( pFd->pMapRegion!=0 ); + *pp = &((u8 *)pFd->pMapRegion)[iOff]; + pFd->nFetchOut++; +@@ -48304,9 +51133,10 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){ + } + + /* +-** If sqlite3_temp_directory is not, take the mutex and return true. ++** If sqlite3_temp_directory is defined, take the mutex and return true. + ** +-** If sqlite3_temp_directory is NULL, omit the mutex and return false. ++** If sqlite3_temp_directory is NULL (undefined), omit the mutex and ++** return false. + */ + static int winTempDirDefined(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); +@@ -48325,6 +51155,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + size_t i, j; ++ DWORD pid; + int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX); + int nMax, nBuf, nDir, nLen; + char *zBuf; +@@ -48537,7 +51368,10 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ + + 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; +@@ -48775,7 +51609,7 @@ static int winOpen( + if( isReadWrite ){ + int rc2, isRO = 0; + sqlite3BeginBenignMalloc(); +- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); ++ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); + sqlite3EndBenignMalloc(); + if( rc2==SQLITE_OK && isRO ) break; + } +@@ -48792,7 +51626,7 @@ static int winOpen( + if( isReadWrite ){ + int rc2, isRO = 0; + sqlite3BeginBenignMalloc(); +- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); ++ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); + sqlite3EndBenignMalloc(); + if( rc2==SQLITE_OK && isRO ) break; + } +@@ -48812,7 +51646,7 @@ static int winOpen( + if( isReadWrite ){ + int rc2, isRO = 0; + sqlite3BeginBenignMalloc(); +- rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); ++ rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO); + sqlite3EndBenignMalloc(); + if( rc2==SQLITE_OK && isRO ) break; + } +@@ -49035,6 +51869,13 @@ static int winAccess( + 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)); +@@ -49342,7 +52183,8 @@ static int winFullPathname( + char *zFull /* Output buffer */ + ){ + int rc; +- sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); ++ 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); +@@ -49884,6 +52726,7 @@ 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 */ +@@ -49942,7 +52785,7 @@ static const sqlite3_io_methods memdb_io_methods = { + memdbSync, /* xSync */ + memdbFileSize, /* xFileSize */ + memdbLock, /* xLock */ +- memdbLock, /* xUnlock - same as xLock in this case */ ++ memdbUnlock, /* xUnlock */ + 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ + memdbFileControl, /* xFileControl */ + 0, /* memdbSectorSize,*/ /* xSectorSize */ +@@ -50143,39 +52986,81 @@ 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; ++ if( eLock<=pThis->eLock ) return SQLITE_OK; + memdbEnter(p); +- if( eLock>SQLITE_LOCK_SHARED ){ +- if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){ +- rc = SQLITE_READONLY; +- }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){ +- if( p->nWrLock ){ +- rc = SQLITE_BUSY; +- }else{ +- p->nWrLock = 1; ++ ++ 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; + } + } +- }else if( eLock==SQLITE_LOCK_SHARED ){ +- if( pThis->eLock > SQLITE_LOCK_SHARED ){ +- assert( p->nWrLock==1 ); +- p->nWrLock = 0; +- }else if( p->nWrLock ){ +- rc = SQLITE_BUSY; +- }else{ +- p->nRdLock++; ++ } ++ 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{ +- assert( eLock==SQLITE_LOCK_NONE ); + if( pThis->eLock>SQLITE_LOCK_SHARED ){ +- assert( p->nWrLock==1 ); +- p->nWrLock = 0; ++ p->nWrLock--; + } +- assert( p->nRdLock>0 ); + p->nRdLock--; + } +- if( rc==SQLITE_OK ) pThis->eLock = eLock; ++ ++ pThis->eLock = eLock; + memdbLeave(p); +- return rc; ++ return SQLITE_OK; + } + + #if 0 +@@ -50285,7 +53170,7 @@ static int memdbOpen( + + memset(pFile, 0, sizeof(*pFile)); + szName = sqlite3Strlen30(zName); +- if( szName>1 && zName[0]=='/' ){ ++ if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){ + int i; + #ifndef SQLITE_MUTEX_OMIT + sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); +@@ -50632,6 +53517,13 @@ end_deserialize: + 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. +@@ -50844,7 +53736,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ + h = BITVEC_HASH(i++); + /* if there wasn't a hash collision, and this doesn't */ + /* completely fill the hash, then just add it without */ +- /* worring about sub-dividing and re-hashing. */ ++ /* worrying about sub-dividing and re-hashing. */ + if( !p->u.aHash[h] ){ + if (p->nSet<(BITVEC_NINT-1)) { + goto bitvec_set_end; +@@ -51111,7 +54003,7 @@ bitvec_end: + struct PCache { + PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ + PgHdr *pSynced; /* Last synced page in dirty page list */ +- int nRefSum; /* Sum of ref counts over all pages */ ++ 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 */ +@@ -51136,12 +54028,24 @@ struct PCache { + 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;} +- void pcacheDump(PCache *pCache){ +- int N; +- int i, j; +- sqlite3_pcache_page *pLower; ++ 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; +@@ -51149,22 +54053,42 @@ struct PCache { + if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; + for(i=1; i<=N; i++){ + pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); +- if( pLower==0 ) continue; +- pPg = (PgHdr*)pLower->pExtra; +- printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags); +- a = (unsigned char *)pLower->pBuf; +- for(j=0; j<12; j++) printf("%02x", a[j]); +- printf("\n"); +- if( pPg->pPage==0 ){ ++ pcachePageTrace(i, pLower); ++ if( pLower && ((PgHdr*)pLower)->pPage==0 ){ + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); + } + } + } +- #else ++#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. +@@ -51183,8 +54107,13 @@ SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ + 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( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */ +- assert( pCache->pDirtyTail!=pPg ); ++ 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 ){ +@@ -51314,7 +54243,7 @@ static int numberOfCachePages(PCache *p){ + return p->szCache; + }else{ + i64 n; +- /* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the ++ /* 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. */ +@@ -51458,8 +54387,9 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch( + 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)\n",pCache,pgno, ++ pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno, + createFlag?" create":"",pRes)); ++ pcachePageTrace(pgno, pRes); + return pRes; + } + +@@ -51587,6 +54517,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ + pcacheUnpin(p); + }else{ + pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); ++ assert( sqlite3PcachePageSanity(p) ); + } + } + } +@@ -51630,6 +54561,7 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ + 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) ); + } +@@ -51799,7 +54731,7 @@ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ + } + + /* +-** Sort the list of pages in accending order by pgno. Pages are ++** Sort the list of pages in ascending order by pgno. Pages are + ** connected by pDirty pointers. The pDirtyPrev pointers are + ** corrupted by this sort. + ** +@@ -51858,14 +54790,14 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){ + ** This is not the total number of pages referenced, but the sum of the + ** reference count for all pages. + */ +-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){ ++SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache *pCache){ + return pCache->nRefSum; + } + + /* + ** Return the number of references to the page supplied as an argument. + */ +-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){ ++SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr *p){ + return p->nRef; + } + +@@ -52007,12 +54939,13 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd + ** size can vary according to architecture, compile-time options, and + ** SQLite library version number. + ** +-** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained +-** using a separate memory allocation from the database page content. This +-** seeks to overcome the "clownshoe" problem (also called "internal +-** fragmentation" in academic literature) of allocating a few bytes more +-** than a power of two with the memory allocator rounding up to the next +-** power of two, and leaving the rounded-up space unused. ++** 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. +@@ -52038,7 +54971,7 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd + ** 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 accomodated. ++** 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 +@@ -52057,30 +54990,40 @@ typedef struct PGroup PGroup; + + /* + ** Each cache entry is represented by an instance of the following +-** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of +-** PgHdr1.pCache->szPage bytes is allocated directly before this structure +-** in memory. ++** 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. + ** +-** Note: Variables isBulkLocal and isAnchor were once type "u8". That works, ++** 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 unitialized gap is accessed. Using u16 +-** ensures there is no such gap, and therefore no bytes of unitialized memory +-** in the structure. ++** 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 LRU list of unpinned pages */ +- PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ +- /* NB: pLruPrev is only valid if pLruNext!=0 */ ++ 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 */ + }; + + /* +@@ -52406,25 +55349,13 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){ + pcache1LeaveMutex(pCache->pGroup); + #endif + if( benignMalloc ){ sqlite3BeginBenignMalloc(); } +-#ifdef SQLITE_PCACHE_SEPARATE_HEADER +- pPg = pcache1Alloc(pCache->szPage); +- p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra); +- if( !pPg || !p ){ +- pcache1Free(pPg); +- sqlite3_free(p); +- pPg = 0; +- } +-#else + pPg = pcache1Alloc(pCache->szAlloc); +-#endif + if( benignMalloc ){ sqlite3EndBenignMalloc(); } + #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pcache1EnterMutex(pCache->pGroup); + #endif + if( pPg==0 ) return 0; +-#ifndef SQLITE_PCACHE_SEPARATE_HEADER + p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; +-#endif + p->page.pBuf = pPg; + p->page.pExtra = &p[1]; + p->isBulkLocal = 0; +@@ -52448,9 +55379,6 @@ static void pcache1FreePage(PgHdr1 *p){ + pCache->pFree = p; + }else{ + pcache1Free(p->page.pBuf); +-#ifdef SQLITE_PCACHE_SEPARATE_HEADER +- sqlite3_free(p); +-#endif + } + (*pCache->pnPurgeable)--; + } +@@ -53217,9 +56145,6 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ + && p->isAnchor==0 + ){ + nFree += pcache1MemSize(p->page.pBuf); +-#ifdef SQLITE_PCACHE_SEPARATE_HEADER +- nFree += sqlite3MemSize(p); +-#endif + assert( PAGE_IS_UNPINNED(p) ); + pcache1PinPage(p); + pcache1RemoveFromHash(p, 1); +@@ -53300,7 +56225,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( + ** 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 nubmer, then the ++** 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. +@@ -53832,6 +56757,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 + # define sqlite3WalFramesize(z) 0 + # define sqlite3WalFindFrame(x,y,z) 0 + # define sqlite3WalFile(x) 0 ++# undef SQLITE_USE_SEH + #else + + #define WAL_SAVEPOINT_NDATA 4 +@@ -53938,6 +56864,10 @@ 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 */ + +@@ -54223,7 +57153,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ + ** 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 peformed) ++** 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. +@@ -54610,7 +57540,7 @@ struct Pager { + char *zJournal; /* Name of the journal file */ + int (*xBusyHandler)(void*); /* Function to call when busy */ + void *pBusyHandlerArg; /* Context argument for xBusyHandler */ +- int aStat[4]; /* Total cache hits, misses, writes, spills */ ++ u32 aStat[4]; /* Total cache hits, misses, writes, spills */ + #ifdef SQLITE_TEST + int nRead; /* Database pages read */ + #endif +@@ -54737,12 +57667,12 @@ static const unsigned char aJournalMagic[] = { + SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ + if( pPager->fd->pMethods==0 ) return 0; + if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; ++ if( sqlite3mcPagerHasCodec(pPager) != 0 ) return 0; + #ifndef SQLITE_OMIT_WAL + if( pPager->pWal ){ + u32 iRead = 0; +- int rc; +- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); +- return (rc==SQLITE_OK && iRead==0); ++ (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); ++ return iRead==0; + } + #endif + return 1; +@@ -54970,7 +57900,7 @@ static void setGetterMethod(Pager *pPager){ + if( pPager->errCode ){ + pPager->xGet = getPageError; + #if SQLITE_MAX_MMAP_SIZE>0 +- }else if( USEFETCH(pPager) ){ ++ }else if( USEFETCH(pPager) && sqlite3mcPagerHasCodec(pPager) == 0 ){ + pPager->xGet = getPageMMap; + #endif /* SQLITE_MAX_MMAP_SIZE>0 */ + }else{ +@@ -55414,9 +58344,32 @@ static int writeJournalHdr(Pager *pPager){ + memset(zHeader, 0, sizeof(aJournalMagic)+4); + } + ++ ++ + /* The random check-hash initializer */ +- sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); ++ 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 */ +@@ -55596,7 +58549,7 @@ static int readJournalHdr( + ** + 4 bytes: super-journal name checksum. + ** + 8 bytes: aJournalMagic[]. + ** +-** The super-journal page checksum is the sum of the bytes in thesuper-journal ++** 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), +@@ -55649,7 +58602,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){ + } + pPager->journalOff += (nSuper+20); + +- /* If the pager is in peristent-journal mode, then the physical ++ /* 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 +@@ -55819,7 +58772,7 @@ static void pager_unlock(Pager *pPager){ + + /* + ** This function is called whenever an IOERR or FULL error that requires +-** the pager to transition into the ERROR state may ahve occurred. ++** 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. +@@ -56060,6 +59013,9 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){ + 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. +@@ -56088,13 +59044,28 @@ static void pagerUnlockAndRollback(Pager *pPager){ + 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 ont the contents of the ++** 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 +@@ -56527,6 +59498,8 @@ 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) +@@ -56857,7 +59830,7 @@ end_playback: + ** see if it is possible to delete the super-journal. + */ + assert( zSuper==&pPager->pTmpSpace[4] ); +- memset(&zSuper[-4], 0, 4); ++ memset(pPager->pTmpSpace, 0, 4); + rc = pager_delsuper(pPager, zSuper); + testcase( rc!=SQLITE_OK ); + } +@@ -57058,7 +60031,7 @@ static int pagerWalFrames( + assert( pPager->pWal ); + assert( pList ); + #ifdef SQLITE_DEBUG +- /* Verify that the page list is in accending order */ ++ /* Verify that the page list is in ascending order */ + for(p=pList; p && p->pDirty; p=p->pDirty){ + assert( p->pgno < p->pDirty->pgno ); + } +@@ -57189,7 +60162,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ + #ifndef SQLITE_OMIT_WAL + /* + ** Check if the *-wal file that corresponds to the database opened by pPager +-** exists if the database is not empy, or verify that the *-wal file does ++** 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 +@@ -57478,7 +60451,6 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){ + ** Numeric values associated with these states are OFF==1, NORMAL=2, + ** and FULL=3. + */ +-#ifndef SQLITE_OMIT_PAGER_PRAGMAS + SQLITE_PRIVATE void sqlite3PagerSetFlags( + Pager *pPager, /* The pager to set safety level for */ + unsigned pgFlags /* Various flags */ +@@ -57513,7 +60485,6 @@ SQLITE_PRIVATE void sqlite3PagerSetFlags( + pPager->doNotSpill |= SPILLFLAG_OFF; + } + } +-#endif + + /* + ** The following global variable is incremented whenever the library +@@ -58601,11 +61572,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + int rc = SQLITE_OK; /* Return code */ + int tempFile = 0; /* True for temp files (incl. in-memory files) */ + int memDb = 0; /* True if this is an in-memory file */ +-#ifndef SQLITE_OMIT_DESERIALIZE + int memJM = 0; /* Memory journal mode */ +-#else +-# define memJM 0 +-#endif + 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 */ +@@ -58615,7 +61582,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + 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 */ +- int nUri = 0; /* Number of URI parameters */ + + /* Figure out how much space is required for each journal file-handle + ** (there are two of them, the main journal and the sub-journal). */ +@@ -58663,7 +61629,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + while( *z ){ + z += strlen(z)+1; + z += strlen(z)+1; +- nUri++; + } + nUriByte = (int)(&z[1] - zUri); + assert( nUriByte>=1 ); +@@ -58726,12 +61691,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + ** 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 */ + journalFileSize * 2 + /* The two journal files */ +- sizeof(pPager) + /* Space to hold a pointer */ ++ SQLITE_PTRSIZE + /* Space to hold a pointer */ + 4 + /* Database prefix */ + nPathname + 1 + /* database filename */ + nUriByte + /* query parameters */ +@@ -58752,7 +61718,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; + pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize; + assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) ); +- memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager); ++ memcpy(pPtr, &pPager, SQLITE_PTRSIZE); pPtr += SQLITE_PTRSIZE; + + /* Fill in the Pager.zFilename and pPager.zQueryParam fields */ + pPtr += 4; /* Skip zero prefix */ +@@ -58806,9 +61772,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( + int fout = 0; /* VFS flags returned by xOpen() */ + rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); + assert( !memDb ); +-#ifndef SQLITE_OMIT_DESERIALIZE + pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0; +-#endif + readOnly = (fout&SQLITE_OPEN_READONLY)!=0; + + /* If the file was successfully opened for read/write access, +@@ -58919,18 +61883,7 @@ act_like_temp_file: + pPager->memDb = (u8)memDb; + pPager->readOnly = (u8)readOnly; + assert( useJournal || pPager->tempFile ); +- pPager->noSync = pPager->tempFile; +- if( pPager->noSync ){ +- assert( pPager->fullSync==0 ); +- assert( pPager->extraSync==0 ); +- assert( pPager->syncFlags==0 ); +- assert( pPager->walSyncFlags==0 ); +- }else{ +- pPager->fullSync = 1; +- pPager->extraSync = 0; +- pPager->syncFlags = SQLITE_SYNC_NORMAL; +- pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2); +- } ++ sqlite3PagerSetFlags(pPager, (SQLITE_DEFAULT_SYNCHRONOUS+1)|PAGER_CACHESPILL); + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ +@@ -58956,15 +61909,18 @@ act_like_temp_file: + + /* + ** Return the sqlite3_file for the main database given the name +-** of the corresonding WAL or Journal name as passed into ++** 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--; + } +- pPager = *(Pager**)(zName - 4 - sizeof(Pager*)); ++ p = zName - 4 - sizeof(Pager*); ++ assert( EIGHT_BYTE_ALIGNMENT(p) ); ++ pPager = *(Pager**)p; + return pPager->fd; + } + +@@ -59459,6 +62415,10 @@ static int getPageNormal( + if( !isOpen(pPager->fd) || pPager->dbSize pPager->mxPgno ){ + rc = SQLITE_FULL; ++ if( pgno<=pPager->dbSize ){ ++ sqlite3PcacheRelease(pPg); ++ pPg = 0; ++ } + goto pager_acquire_err; + } + if( noContent ){ +@@ -59594,8 +62554,20 @@ SQLITE_PRIVATE int sqlite3PagerGet( + DbPage **ppPage, /* Write a pointer to the page here */ + int flags /* PAGER_GET_XXX flags */ + ){ +- /* printf("PAGE %u\n", pgno); fflush(stdout); */ ++#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 + } + + /* +@@ -59623,10 +62595,12 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ + /* + ** Release a page reference. + ** +-** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be +-** used if we know that the page being released is not the last page. ++** 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 +-** to routines can be used to release any page other than BtShared.pPage1. ++** 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 +@@ -59642,7 +62616,7 @@ SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ + sqlite3PcacheRelease(pPg); + } + /* Do not use this routine to release the last reference to page1 */ +- assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); ++ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); /* tag-20230419-2 */ + } + SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ + if( pPg ) sqlite3PagerUnrefNotNull(pPg); +@@ -59708,6 +62682,7 @@ static int pager_open_journal(Pager *pPager){ + + if( pPager->tempFile ){ + flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); ++ flags |= SQLITE_OPEN_EXCLUSIVE; + nSpill = sqlite3Config.nStmtSpill; + }else{ + flags |= SQLITE_OPEN_MAIN_JOURNAL; +@@ -60190,7 +63165,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ + # define DIRECT_MODE isDirectMode + #endif + +- if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){ ++ if( !pPager->changeCountDone && pPager->dbSize>0 ){ + PgHdr *pPgHdr; /* Reference to page 1 */ + + assert( !pPager->tempFile && isOpen(pPager->fd) ); +@@ -60468,6 +63443,13 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( + 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); + } +@@ -60702,11 +63684,11 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ + a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; + a[4] = pPager->eState; + a[5] = pPager->errCode; +- a[6] = pPager->aStat[PAGER_STAT_HIT]; +- a[7] = pPager->aStat[PAGER_STAT_MISS]; ++ 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] = pPager->aStat[PAGER_STAT_WRITE]; ++ a[10] = (int)pPager->aStat[PAGER_STAT_WRITE] & 0x7fffffff; + return a; + } + #endif +@@ -60722,7 +63704,7 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ + ** 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, int *pnVal){ ++SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, u64 *pnVal){ + + assert( eStat==SQLITE_DBSTATUS_CACHE_HIT + || eStat==SQLITE_DBSTATUS_CACHE_MISS +@@ -60930,7 +63912,11 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ + */ + SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){ + static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +- return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename; ++ if( nullIfMemDb && (pPager->memDb || sqlite3IsMemdb(pPager->pVfs)) ){ ++ return &zFake[4]; ++ }else{ ++ return pPager->zFilename; ++ } + } + + /* +@@ -61230,7 +64216,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ + assert( pPager->eState!=PAGER_ERROR ); + pPager->journalMode = (u8)eMode; + +- /* When transistioning from TRUNCATE or PERSIST to any other journal ++ /* 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. + */ +@@ -61275,7 +64261,7 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ + } + assert( state==pPager->eState ); + } +- }else if( eMode==PAGER_JOURNALMODE_OFF ){ ++ }else if( eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ){ + sqlite3OsClose(pPager->jfd); + } + } +@@ -61299,7 +64285,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ + SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ + assert( assert_pager_state(pPager) ); + if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; +- if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0; ++ if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; + return 1; + } + +@@ -61397,13 +64383,15 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ + */ + static int pagerExclusiveLock(Pager *pPager){ + int rc; /* Return code */ ++ u8 eOrigLock; /* Original lock */ + +- assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_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, SHARED_LOCK); ++ pagerUnlockDb(pPager, eOrigLock); + } + + return rc; +@@ -61656,6 +64644,12 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ + } + #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 */ + + /************** End of pager.c ***********************************************/ +@@ -61946,7 +64940,7 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0; + ** + ** 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 implemention used on both unix and windows ++** 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 +@@ -62022,7 +65016,7 @@ struct WalIndexHdr { + ** 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[] indexs by one. Readers holding ++** 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. + ** +@@ -62190,7 +65184,15 @@ struct Wal { + 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 +@@ -62272,6 +65274,113 @@ struct WalIterator { + 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 +@@ -62344,6 +65453,7 @@ static int walIndexPage( + 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); + } +@@ -62355,6 +65465,7 @@ static int walIndexPage( + */ + 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]); + } + +@@ -62363,6 +65474,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ + */ + static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ + assert( pWal->nWiData>0 && pWal->apWiData[0] ); ++ SEH_INJECT_FAULT; + return (volatile WalIndexHdr*)pWal->apWiData[0]; + } + +@@ -62408,19 +65520,40 @@ static void walChecksumBytes( + assert( nByte>=8 ); + assert( (nByte&0x00000007)==0 ); + assert( nByte<=65536 ); ++ assert( nByte%4==0 ); + +- if( nativeCksum ){ ++ if( !nativeCksum ){ ++ do { ++ s1 += BYTESWAP32(aData[0]) + s2; ++ s2 += BYTESWAP32(aData[1]) + s1; ++ aData += 2; ++ }while( aData 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){ +@@ -62615,12 +65754,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ + 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< apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; + } +@@ -62971,6 +66119,7 @@ static int walIndexRecover(Wal *pWal){ + /* 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; +@@ -62989,6 +66138,7 @@ static int walIndexRecover(Wal *pWal){ + 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++){ +@@ -63016,6 +66166,7 @@ static int walIndexRecover(Wal *pWal){ + } + } + 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 +@@ -63046,9 +66197,11 @@ static int walIndexRecover(Wal *pWal){ + } + } + #endif ++ SEH_INJECT_FAULT; + if( iFrame<=iLast ) break; + } + ++ SEH_FREE_ON_ERROR(aFrame, 0); + sqlite3_free(aFrame); + } + +@@ -63076,6 +66229,7 @@ finished: + }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; +@@ -63233,7 +66387,7 @@ SQLITE_PRIVATE int sqlite3WalOpen( + } + + /* +-** Change the size to which the WAL file is trucated on each reset. ++** 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; +@@ -63459,23 +66613,16 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ + nByte = sizeof(WalIterator) + + (nSegment-1)*sizeof(struct WalSegment) + + iLast*sizeof(ht_slot); +- p = (WalIterator *)sqlite3_malloc64(nByte); ++ 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; +- +- /* Allocate temporary space used by the merge-sort routine. This block +- ** of memory will be freed before this function returns. +- */ +- aTmp = (ht_slot *)sqlite3_malloc64( +- sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) +- ); +- if( !aTmp ){ +- rc = SQLITE_NOMEM_BKPT; +- } +- ++ aTmp = (ht_slot*)&(((u8*)p)[nByte]); ++ SEH_FREE_ON_ERROR(0, p); + for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i aSegment[i].aPgno = (u32 *)sLoc.aPgno; + } + } +- sqlite3_free(aTmp); +- + if( rc!=SQLITE_OK ){ ++ SEH_FREE_ON_ERROR(p, 0); + walIteratorFree(p); + p = 0; + } +@@ -63514,6 +66660,19 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ + } + + #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 +@@ -63525,11 +66684,7 @@ static int walEnableBlocking(Wal *pWal){ + if( pWal->db ){ + int tmout = pWal->db->busyTimeout; + if( tmout ){ +- int rc; +- rc = sqlite3OsFileControl( +- pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout +- ); +- res = (rc==SQLITE_OK); ++ res = walEnableBlockingMs(pWal, tmout); + } + } + return res; +@@ -63578,20 +66733,10 @@ SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){ + pWal->db = db; + } + +-/* +-** Take an exclusive WRITE lock. Blocking if so configured. +-*/ +-static int walLockWriter(Wal *pWal){ +- int rc; +- walEnableBlocking(pWal); +- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); +- walDisableBlocking(pWal); +- return rc; +-} + #else + # define walEnableBlocking(x) 0 + # define walDisableBlocking(x) +-# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1) ++# define walEnableBlockingMs(pWal, ms) 0 + # define sqlite3WalDb(pWal, db) + #endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ + +@@ -63731,13 +66876,13 @@ static int walCheckpoint( + mxSafeFrame = pWal->hdr.mxFrame; + mxPage = pWal->hdr.nPage; + for(i=1; i aReadMark+i); ++ u32 y = AtomicLoad(pInfo->aReadMark+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); ++ AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; + walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); + }else if( rc==SQLITE_BUSY ){ + mxSafeFrame = y; +@@ -63758,8 +66903,7 @@ static int walCheckpoint( + && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK + ){ + u32 nBackfill = pInfo->nBackfill; +- +- pInfo->nBackfillAttempted = mxSafeFrame; ++ pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; + + /* Sync the WAL to disk */ + rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); +@@ -63790,6 +66934,7 @@ static int walCheckpoint( + 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; +@@ -63819,7 +66964,7 @@ static int walCheckpoint( + } + } + if( rc==SQLITE_OK ){ +- AtomicStore(&pInfo->nBackfill, mxSafeFrame); ++ AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; + } + } + +@@ -63841,6 +66986,7 @@ static int walCheckpoint( + */ + if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ + assert( pWal->writeLock ); ++ SEH_INJECT_FAULT; + if( pInfo->nBackfill hdr.mxFrame ){ + rc = SQLITE_BUSY; + }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ +@@ -63872,6 +67018,7 @@ static int walCheckpoint( + } + + walcheckpoint_out: ++ SEH_FREE_ON_ERROR(pIter, 0); + walIteratorFree(pIter); + return rc; + } +@@ -63894,6 +67041,93 @@ static void walLimitSize(Wal *pWal, i64 nMax){ + } + } + ++#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< 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; ii pFree); ++ 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 connenction, 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. + */ +@@ -63908,6 +67142,8 @@ SQLITE_PRIVATE int sqlite3WalClose( + 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 +@@ -63932,7 +67168,7 @@ SQLITE_PRIVATE int sqlite3WalClose( + ); + if( bPersist!=1 ){ + /* Try to delete the WAL file if the checkpoint completed and +- ** fsyned (rc==SQLITE_OK) and if we are not in persistent-wal ++ ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal + ** mode (!bPersist) */ + isDelete = 1; + }else if( pWal->mxWalSize>=0 ){ +@@ -63999,7 +67235,7 @@ static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){ + ** 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 implementions work ++ ** shared among multiple processes and not all mutex implementations work + ** reliably in that environment. + */ + aHdr = walIndexHdr(pWal); +@@ -64101,7 +67337,9 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ + } + }else{ + int bWriteLock = pWal->writeLock; +- if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){ ++ if( bWriteLock ++ || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ++ ){ + pWal->writeLock = 1; + if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ + badHdr = walIndexTryHdr(pWal, pChanged); +@@ -64109,7 +67347,8 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ + /* 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; + } +@@ -64319,6 +67558,37 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ + 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 +@@ -64369,13 +67639,16 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ + ** 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 cnt){ ++static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){ + volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */ + u32 mxReadMark; /* Largest aReadMark[] value */ + int mxI; /* Index of largest aReadMark[] value */ + int i; /* Loop counter */ + int rc = SQLITE_OK; /* Return code */ + u32 mxFrame; /* Wal frame to lock to */ ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ int nBlockTmout = 0; ++#endif + + assert( pWal->readLock<0 ); /* Not currently locked */ + +@@ -64399,14 +67672,34 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + ** so that on the 100th (and last) RETRY we delay for 323 milliseconds. + ** The total delay time before giving up is less than 10 seconds. + */ +- if( cnt>5 ){ ++ (*pCnt)++; ++ if( *pCnt>5 ){ + int nDelay = 1; /* Pause time in microseconds */ +- if( cnt>100 ){ ++ int cnt = (*pCnt & ~WAL_RETRY_BLOCKED_MASK); ++ if( cnt>WAL_RETRY_PROTOCOL_LIMIT ){ + VVA_ONLY( pWal->lockError = 1; ) + return SQLITE_PROTOCOL; + } +- if( cnt>=10 ) nDelay = (cnt-9)*(cnt-9)*39; ++ 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 ){ +@@ -64414,6 +67707,13 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + if( pWal->bShmUnreliable==0 ){ + rc = walIndexReadHdr(pWal, pChanged); + } ++#ifdef SQLITE_ENABLE_SETLK_TIMEOUT ++ walDisableBlocking(pWal); ++ 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 +@@ -64450,6 +67750,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + assert( pWal->nWiData>0 ); + assert( pWal->apWiData[0]!=0 ); + pInfo = walCkptInfo(pWal); ++ SEH_INJECT_FAULT; + if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame + #ifdef SQLITE_ENABLE_SNAPSHOT + && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) +@@ -64499,7 +67800,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + } + #endif + for(i=1; i aReadMark+i); ++ u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; + if( mxReadMark<=thisMark && thisMark<=mxFrame ){ + assert( thisMark!=READMARK_NOT_USED ); + mxReadMark = thisMark; +@@ -64527,9 +67828,19 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT; + } + ++ (void)walEnableBlockingMs(pWal, nBlockTmout); + rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); ++ walDisableBlocking(pWal); + if( rc ){ +- return rc==SQLITE_BUSY ? WAL_RETRY : 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 +@@ -64565,7 +67876,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + ** 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; ++ 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)) +@@ -64580,6 +67891,54 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ + } + + #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 +@@ -64605,50 +67964,21 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ + assert( pWal->readLock>=0 ); + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + if( rc==SQLITE_OK ){ +- volatile WalCkptInfo *pInfo = walCkptInfo(pWal); +- int szPage = (int)pWal->szPage; +- i64 szDb; /* Size of db file in bytes */ +- +- rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); +- if( rc==SQLITE_OK ){ +- void *pBuf1 = sqlite3_malloc(szPage); +- void *pBuf2 = sqlite3_malloc(szPage); +- if( pBuf1==0 || pBuf2==0 ){ +- rc = SQLITE_NOMEM; +- }else{ +- 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; +- } ++ 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); + } +- +- sqlite3_free(pBuf1); +- sqlite3_free(pBuf2); ++ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) ++ pWal->ckptLock = 0; + } ++ ++ sqlite3_free(pBuf1); ++ sqlite3_free(pBuf2); + walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); + } + +@@ -64657,28 +67987,20 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ + #endif /* SQLITE_ENABLE_SNAPSHOT */ + + /* +-** 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. ++** This function does the work of sqlite3WalBeginReadTransaction() (see ++** below). That function simply calls this one inside an SEH_TRY{...} block. + */ +-SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ++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 ){ +@@ -64701,12 +68023,12 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + if( rc!=SQLITE_OK ){ + return rc; + } +- pWal->ckptLock = 1; ++ ckptLock = 1; + } + #endif + + do{ +- rc = walTryBeginRead(pWal, pChanged, 0, ++cnt); ++ rc = walTryBeginRead(pWal, pChanged, 0, &cnt); + }while( rc==WAL_RETRY ); + testcase( (rc&0xff)==SQLITE_BUSY ); + testcase( (rc&0xff)==SQLITE_IOERR ); +@@ -64765,15 +68087,37 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + } + + /* Release the shared CKPT lock obtained above. */ +- if( pWal->ckptLock ){ ++ if( ckptLock ){ + assert( pSnapshot ); + walUnlockShared(pWal, WAL_CKPT_LOCK); +- pWal->ckptLock = 0; + } + #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. +@@ -64794,7 +68138,7 @@ SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){ + ** 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. + */ +-SQLITE_PRIVATE int sqlite3WalFindFrame( ++static int walFindFrame( + Wal *pWal, /* WAL handle */ + Pgno pgno, /* Database page number to read data for */ + u32 *piRead /* OUT: Frame number (or zero) */ +@@ -64857,6 +68201,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( + } + 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 ){ +@@ -64864,6 +68209,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( + iRead = iFrame; + } + if( (nCollide--)==0 ){ ++ *piRead = 0; + return SQLITE_CORRUPT_BKPT; + } + iKey = walNextHash(iKey); +@@ -64893,6 +68239,30 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( + 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 +@@ -64974,12 +68344,17 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){ + ** time the read transaction on this connection was started, then + ** the write is disallowed. + */ +- if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ ++ 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; +- rc = SQLITE_BUSY_SNAPSHOT; + } +- + return rc; + } + +@@ -65015,30 +68390,33 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p + Pgno iMax = pWal->hdr.mxFrame; + Pgno iFrame; + +- /* 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. ++ 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. + */ +- assert( walFramePgno(pWal, iFrame)!=1 ); +- rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); ++ 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); + } +- if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); ++ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + } + return rc; + } +@@ -65082,7 +68460,10 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ + pWal->hdr.mxFrame = aWalData[0]; + pWal->hdr.aFrameCksum[0] = aWalData[1]; + pWal->hdr.aFrameCksum[1] = aWalData[2]; +- walCleanupHash(pWal); ++ SEH_TRY { ++ walCleanupHash(pWal); ++ } ++ SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) + } + + return rc; +@@ -65132,7 +68513,7 @@ static int walRestartLog(Wal *pWal){ + cnt = 0; + do{ + int notUsed; +- rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt); ++ 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 ); +@@ -65197,7 +68578,7 @@ static int walWriteOneFrame( + int rc; /* Result code from subfunctions */ + void *pData; /* Data actually written */ + u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */ +- pData = pPage->pData; ++ if( (pData = sqlite3mcPagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT; + walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame); + rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset); + if( rc ) return rc; +@@ -65263,7 +68644,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){ + ** Write a set of frames to the log. The caller must hold the write-lock + ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). + */ +-SQLITE_PRIVATE int sqlite3WalFrames( ++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 */ +@@ -65351,7 +68732,9 @@ SQLITE_PRIVATE int sqlite3WalFrames( + if( rc ) return rc; + } + } +- assert( (int)pWal->szPage==szPage ); ++ 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; +@@ -65372,7 +68755,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( + ** checksums must be recomputed when the transaction is committed. */ + if( iFirst && (p->pDirty || isCommit==0) ){ + u32 iWrite = 0; +- VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); ++ 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; +@@ -65380,7 +68763,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( + if( pWal->iReCksum==0 || iWrite iReCksum ){ + pWal->iReCksum = iWrite; + } +- pData = p->pData; ++ if( (pData = sqlite3mcPagerCodec(p))==0 ) return SQLITE_NOMEM; + rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff); + if( rc ) return rc; + p->flags &= ~PGHDR_WAL_APPEND; +@@ -65491,6 +68874,29 @@ SQLITE_PRIVATE int sqlite3WalFrames( + 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. +@@ -65528,10 +68934,9 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( + if( pWal->readOnly ) return SQLITE_READONLY; + WALTRACE(("WAL%p: checkpoint begins\n", pWal)); + +- /* Enable blocking locks, if possible. If blocking locks are successfully +- ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ ++ /* Enable blocking locks, if possible. */ + sqlite3WalDb(pWal, db); +- (void)walEnableBlocking(pWal); ++ if( xBusy2 ) (void)walEnableBlocking(pWal); + + /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive + ** "checkpoint" lock on the database file. +@@ -65570,30 +68975,38 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint( + + + /* Read the wal-index header. */ +- if( rc==SQLITE_OK ){ +- walDisableBlocking(pWal); +- rc = walIndexReadHdr(pWal, &isChanged); +- (void)walEnableBlocking(pWal); +- if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ +- sqlite3OsUnfetch(pWal->pDbFd, 0, 0); ++ 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); +- } ++ /* 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; +- if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); ++ /* 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 +@@ -65670,7 +69083,9 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){ + ** 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 ){ +@@ -65771,16 +69186,19 @@ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ + */ + SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ + int rc; +- 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->mxFrame nBackfillAttempted +- ){ +- rc = SQLITE_ERROR_SNAPSHOT; +- walUnlockShared(pWal, WAL_CKPT_LOCK); ++ 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->mxFrame nBackfillAttempted ++ ){ ++ rc = SQLITE_ERROR_SNAPSHOT; ++ walUnlockShared(pWal, WAL_CKPT_LOCK); ++ } + } + } ++ SEH_EXCEPT( rc = walHandleException(pWal); ) + return rc; + } + +@@ -65903,7 +69321,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ + ** 22 1 Min embedded payload fraction (must be 32) + ** 23 1 Min leaf payload fraction (must be 32) + ** 24 4 File change counter +-** 28 4 Reserved for future use ++** 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 +@@ -66011,7 +69429,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ + ** byte are used. The integer consists of all bytes that have bit 8 set and + ** the first byte with bit 8 clear. The most significant byte of the integer + ** appears first. A variable-length integer may not be more than 9 bytes long. +-** As a special case, all 8 bytes of the 9th byte are used as data. This ++** 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 +@@ -66019,7 +69437,7 @@ SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){ + ** 0x81 0x00 becomes 0x00000080 + ** 0x82 0x00 becomes 0x00000100 + ** 0x80 0x7f becomes 0x0000007f +-** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 ++** 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 +@@ -66102,7 +69520,7 @@ typedef struct CellInfo CellInfo; + ** page that has been loaded into memory. The information in this object + ** is derived from the raw on-disk page content. + ** +-** As each database page is loaded into memory, the pager allocats an ++** 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.) + ** +@@ -66395,7 +69813,7 @@ struct BtCursor { + #define BTCF_WriteFlag 0x01 /* True if a write cursor */ + #define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */ + #define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */ +-#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */ ++#define BTCF_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 */ +@@ -66513,15 +69931,15 @@ struct BtCursor { + ** So, this macro is defined instead. + */ + #ifndef SQLITE_OMIT_AUTOVACUUM +-#define ISAUTOVACUUM (pBt->autoVacuum) ++#define ISAUTOVACUUM(pBt) (pBt->autoVacuum) + #else +-#define ISAUTOVACUUM 0 ++#define ISAUTOVACUUM(pBt) 0 + #endif + + + /* +-** This structure is passed around through all the sanity checking routines +-** in order to keep track of some global state information. ++** 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 +@@ -66534,13 +69952,15 @@ struct IntegrityCk { + BtShared *pBt; /* The tree being checked out */ + Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ + u8 *aPgRef; /* 1 bit per page in the db (see above) */ +- Pgno nPage; /* Number of pages in the database */ ++ 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 bOomFault; /* A memory allocation error has occurred */ ++ 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 v1; /* Value for first %u substitution in zPfx */ +- int v2; /* Value for second %d substitution in zPfx */ ++ 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 */ +@@ -66556,7 +69976,7 @@ struct IntegrityCk { + + /* + ** get2byteAligned(), unlike get2byte(), requires that its argument point to a +-** two-byte aligned address. get2bytea() is only used for accessing the ++** two-byte aligned address. get2byteAligned() is only used for accessing the + ** cell addresses in a btree header. + */ + #if SQLITE_BYTEORDER==4321 +@@ -66733,7 +70153,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){ + ** + ** There is a corresponding leave-all procedures. + ** +-** Enter the mutexes in accending order by BtShared pointer address ++** 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. +@@ -66807,6 +70227,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ + 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 && iDb nDb ); + if( !sqlite3_mutex_held(db->mutex) ) return 0; +@@ -67002,8 +70423,8 @@ SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){ + int corruptPageError(int lineno, MemPage *p){ + char *zMsg; + sqlite3BeginBenignMalloc(); +- zMsg = sqlite3_mprintf("database corruption page %d of %s", +- (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) ++ zMsg = sqlite3_mprintf("database corruption page %u of %s", ++ p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) + ); + sqlite3EndBenignMalloc(); + if( zMsg ){ +@@ -67812,8 +71233,25 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow) + */ + 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 ++#endif /* SQLITE_ENABLE_CURSOR_HINTS */ ++ + + /* + ** Provide flag hints to the cursor. +@@ -67898,7 +71336,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){ + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ +- TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); ++ TRACE(("PTRMAP_UPDATE: %u->(%u,%u)\n", key, eType, parent)); + *pRC= rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK ){ + pPtrmap[offset] = eType; +@@ -68097,27 +71535,31 @@ static void btreeParseCellPtr( + iKey = *pIter; + if( iKey>=0x80 ){ + u8 x; +- iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<7) | ((x =*++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ 0x10204000 ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); ++ iKey = (iKey<<7) ^ 0x4000 ^ (x = *++pIter); + if( x>=0x80 ){ +- iKey = (iKey<<8) | (*++pIter); ++ iKey = (iKey<<8) ^ 0x8000 ^ (*++pIter); + } + } + } + } + } ++ }else{ ++ iKey ^= 0x204000; + } ++ }else{ ++ iKey ^= 0x4000; + } + } + pIter++; +@@ -68194,10 +71636,53 @@ static void btreeParseCell( + ** + ** cellSizePtrNoPayload() => table internal nodes + ** cellSizePtrTableLeaf() => table leaf nodes +-** cellSizePtr() => all index nodes & table leaf nodes ++** cellSizePtr() => index internal nodes ++** cellSizeIdxLeaf() => index leaf nodes + */ + static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ +- u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of 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 && pIter maxLocal ); ++ 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 */ + +@@ -68210,6 +71695,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ + pPage->xParseCell(pPage, pCell, &debuginfo); + #endif + ++ assert( pPage->childPtrSize==0 ); + nSize = *pIter; + if( nSize>=0x80 ){ + pEnd = &pIter[8]; +@@ -68334,7 +71820,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){ + pPage->xParseCell(pPage, pCell, &info); + if( info.nLocal aDataEnd, pCell, pCell+info.nLocal) ){ ++ if( SQLITE_OVERFLOW(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){ + testcase( pSrc!=pPage ); + *pRC = SQLITE_CORRUPT_BKPT; + return; +@@ -68379,8 +71865,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ + assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); +- temp = 0; +- src = data = pPage->aData; ++ data = pPage->aData; + hdr = pPage->hdrOffset; + cellOffset = pPage->cellOffset; + nCell = pPage->nCell; +@@ -68434,39 +71919,38 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ + cbrk = usableSize; + iCellLast = usableSize - 4; + iCellStart = get2byte(&data[hdr+5]); +- for(i=0; i iCellLast ){ +- return SQLITE_CORRUPT_PAGE(pPage); +- } +- assert( pc>=iCellStart && pc<=iCellLast ); +- size = pPage->xCellSize(pPage, &src[pc]); +- cbrk -= size; +- if( cbrk usableSize ){ +- return SQLITE_CORRUPT_PAGE(pPage); +- } +- assert( cbrk+size<=usableSize && cbrk>=iCellStart ); +- testcase( cbrk+size==usableSize ); +- testcase( pc+size==usableSize ); +- put2byte(pAddr, cbrk); +- if( temp==0 ){ +- if( cbrk==pc ) continue; +- temp = sqlite3PagerTempSpace(pPage->pBt->pPager); +- memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart); +- src = temp; ++ if( nCell>0 ){ ++ temp = sqlite3PagerTempSpace(pPage->pBt->pPager); ++ memcpy(temp, data, usableSize); ++ src = temp; ++ for(i=0; i iCellLast ){ ++ return SQLITE_CORRUPT_PAGE(pPage); ++ } ++ assert( pc>=0 && pc<=iCellLast ); ++ size = pPage->xCellSize(pPage, &src[pc]); ++ cbrk -= size; ++ if( cbrk usableSize ){ ++ 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); + } +- memcpy(&data[cbrk], &src[pc], size); + } + data[hdr+7] = 0; + +- defragment_out: ++defragment_out: + assert( pPage->nFree>=0 ); + if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ + return SQLITE_CORRUPT_PAGE(pPage); +@@ -68523,7 +72007,6 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ + ** fragmented bytes within the page. */ + memcpy(&aData[iAddr], &aData[pc], 2); + aData[hdr+7] += (u8)x; +- testcase( pc+x>maxPC ); + return &aData[pc]; + }else if( x+pc > maxPC ){ + /* This slot extends off the end of the usable part of the page */ +@@ -68539,9 +72022,9 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ + iAddr = pc; + pTmp = &aData[pc]; + pc = get2byte(pTmp); +- if( pc<=iAddr+size ){ ++ if( pc<=iAddr ){ + if( pc ){ +- /* The next slot in the chain is not past the end of the current slot */ ++ /* The next slot in the chain comes before the current slot */ + *pRc = SQLITE_CORRUPT_PAGE(pPg); + } + return 0; +@@ -68567,7 +72050,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ + ** allocation is being made in order to insert a new cell, so we will + ** also end up needing a new cell pointer. + */ +-static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ ++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 */ +@@ -68593,13 +72076,14 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ + ** integer, so a value of 0 is used in its place. */ + pTmp = &data[hdr+5]; + top = get2byte(pTmp); +- assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */ + if( gap>top ){ + if( top==0 && pPage->pBt->usableSize==65536 ){ + 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, +@@ -68661,7 +72145,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ + ** + ** 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 encrouch into the reserved bytes ++** 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. + */ +@@ -68682,7 +72166,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ + assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( iSize>=4 ); /* Minimum cell size is 4 */ +- assert( iStart<=pPage->pBt->usableSize-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. +@@ -68693,7 +72177,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ + iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ + }else{ + while( (iFreeBlk = get2byte(&data[iPtr])) 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 +@@ -68750,14 +72239,9 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ + }else{ + /* Insert the new freeblock into the freelist */ + put2byte(&data[iPtr], iStart); ++ put2byte(&data[iStart], iFreeBlk); ++ put2byte(&data[iStart+2], iSize); + } +- if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ +- /* Overwrite deleted information with zeros when the secure_delete +- ** option is enabled */ +- memset(&data[iStart], 0, iSize); +- } +- put2byte(&data[iStart], iFreeBlk); +- put2byte(&data[iStart+2], iSize); + pPage->nFree += iOrigSize; + return SQLITE_OK; + } +@@ -68769,62 +72253,67 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ + ** Only the following combinations are supported. Anything different + ** indicates a corrupt database files: + ** +-** PTF_ZERODATA +-** PTF_ZERODATA | PTF_LEAF +-** PTF_LEAFDATA | PTF_INTKEY +-** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF ++** 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) ); +- pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); +- flagByte &= ~PTF_LEAF; +- pPage->childPtrSize = 4-4*pPage->leaf; + pBt = pPage->pBt; +- if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ +- /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an +- ** interior table b-tree page. */ +- assert( (PTF_LEAFDATA|PTF_INTKEY)==5 ); +- /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a +- ** leaf table b-tree page. */ +- assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); +- pPage->intKey = 1; +- if( pPage->leaf ){ ++ 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); + } +- pPage->maxLocal = pBt->maxLeaf; +- pPage->minLocal = pBt->minLeaf; +- }else if( flagByte==PTF_ZERODATA ){ +- /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an +- ** interior index b-tree page. */ +- assert( (PTF_ZERODATA)==2 ); +- /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a +- ** leaf index b-tree page. */ +- assert( (PTF_ZERODATA|PTF_LEAF)==10 ); +- pPage->intKey = 0; +- pPage->intKeyLeaf = 0; +- pPage->xCellSize = cellSizePtr; +- pPage->xParseCell = btreeParseCellPtrIndex; +- pPage->maxLocal = pBt->maxLocal; +- pPage->minLocal = pBt->minLocal; +- }else{ +- /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is +- ** an error. */ +- pPage->intKey = 0; +- pPage->intKeyLeaf = 0; +- pPage->xCellSize = cellSizePtr; +- pPage->xParseCell = btreeParseCellPtrIndex; +- return SQLITE_CORRUPT_PAGE(pPage); + } +- pPage->max1bytePayload = pBt->max1bytePayload; + return SQLITE_OK; + } + +@@ -69115,70 +72604,41 @@ SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree *p){ + + /* + ** Get a page from the pager and initialize it. +-** +-** If pCur!=0 then the page is being fetched as part of a moveToChild() +-** call. Do additional sanity checking on the page in this case. +-** And if the fetch fails, this routine must decrement pCur->iPage. +-** +-** The page is fetched as read-write unless pCur is not NULL and is +-** a read-only cursor. +-** +-** If an error occurs, then *ppPage is undefined. It +-** may remain unchanged, or it may be set to an invalid value. + */ + static int getAndInitPage( + BtShared *pBt, /* The database file */ + Pgno pgno, /* Number of the page to get */ + MemPage **ppPage, /* Write the page pointer here */ +- BtCursor *pCur, /* Cursor to receive the page, or NULL */ + int bReadOnly /* True for a read-only page */ + ){ + int rc; + DbPage *pDbPage; ++ MemPage *pPage; + assert( sqlite3_mutex_held(pBt->mutex) ); +- assert( pCur==0 || ppPage==&pCur->pPage ); +- assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); +- assert( pCur==0 || pCur->iPage>0 ); + + if( pgno>btreePagecount(pBt) ){ +- rc = SQLITE_CORRUPT_BKPT; +- goto getAndInitPage_error1; ++ *ppPage = 0; ++ return SQLITE_CORRUPT_BKPT; + } + rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); + if( rc ){ +- goto getAndInitPage_error1; ++ *ppPage = 0; ++ return rc; + } +- *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); +- if( (*ppPage)->isInit==0 ){ ++ pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); ++ if( pPage->isInit==0 ){ + btreePageFromDbPage(pDbPage, pgno, pBt); +- rc = btreeInitPage(*ppPage); ++ rc = btreeInitPage(pPage); + if( rc!=SQLITE_OK ){ +- goto getAndInitPage_error2; ++ releasePage(pPage); ++ *ppPage = 0; ++ return rc; + } + } +- assert( (*ppPage)->pgno==pgno || CORRUPT_DB ); +- assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) ); +- +- /* If obtaining a child page for a cursor, we must verify that the page is +- ** compatible with the root page. */ +- if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ +- rc = SQLITE_CORRUPT_PGNO(pgno); +- goto getAndInitPage_error2; +- } ++ assert( pPage->pgno==pgno || CORRUPT_DB ); ++ assert( pPage->aData==sqlite3PagerGetData(pDbPage) ); ++ *ppPage = pPage; + return SQLITE_OK; +- +-getAndInitPage_error2: +- releasePage(*ppPage); +-getAndInitPage_error1: +- if( pCur ){ +- pCur->iPage--; +- pCur->pPage = pCur->apPage[pCur->iPage]; +- } +- testcase( pgno==0 ); +- assert( pgno!=0 || rc==SQLITE_CORRUPT +- || rc==SQLITE_IOERR_NOMEM +- || rc==SQLITE_NOMEM ); +- return rc; + } + + /* +@@ -69261,7 +72721,7 @@ static void pageReinit(DbPage *pData){ + ** 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-initing. */ ++ ** the call for every page that comes in for re-initializing. */ + btreeInitPage(pPage); + } + } +@@ -69440,6 +72900,9 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( + 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; +@@ -69656,7 +73119,7 @@ static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ + ** can mean that fillInCell() only initializes the first 2 or 3 + ** bytes of pTmpSpace, but that the first 4 bytes are copied from + ** it into a database page. This is not actually a problem, but it +- ** does cause a valgrind error when the 1 or 2 bytes of unitialized ++ ** 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. + ** +@@ -69891,7 +73354,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){ + + /* + ** Return the number of bytes of space at the end of every page that +-** are intentually left unused. This is the "reserved" space that is ++** 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 +@@ -70138,7 +73601,6 @@ static int lockBtree(BtShared *pBt){ + ){ + goto page1_init_failed; + } +- pBt->btsFlags |= BTS_PAGESIZE_FIXED; + 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 +@@ -70158,6 +73620,7 @@ static int lockBtree(BtShared *pBt){ + releasePageOne(pPage1); + pBt->usableSize = usableSize; + pBt->pageSize = pageSize; ++ pBt->btsFlags |= BTS_PAGESIZE_FIXED; + freeTempSpace(pBt); + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, + pageSize-usableSize); +@@ -70177,6 +73640,7 @@ static int lockBtree(BtShared *pBt){ + if( usableSize<480 ){ + goto page1_init_failed; + } ++ pBt->btsFlags |= BTS_PAGESIZE_FIXED; + pBt->pageSize = pageSize; + pBt->usableSize = usableSize; + #ifndef SQLITE_OMIT_AUTOVACUUM +@@ -70355,7 +73819,11 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){ + ** when A already has a read lock, we encourage A to give up and let B + ** proceed. + */ +-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ ++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; +@@ -70527,6 +73995,28 @@ trans_begun: + 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 + +@@ -70613,6 +74103,9 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ + } + } + }else{ ++ if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){ ++ return SQLITE_CORRUPT_PAGE(pPage); ++ } + if( get4byte(pCell)==iFrom ){ + put4byte(pCell, iTo); + break; +@@ -70661,7 +74154,7 @@ static int relocatePage( + if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; + + /* Move page iDbPage from its current location to page number iFreePage */ +- TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", ++ 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 ){ +@@ -71619,7 +75112,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){ + pCur->curFlags &= ~BTCF_Pinned; + } + +-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + /* + ** Return the offset into the database file for the start of the + ** payload to which the cursor is pointing. +@@ -71631,7 +75123,6 @@ SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){ + return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + + (i64)(pCur->info.pPayload - pCur->pPage->aData); + } +-#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ + + /* + ** Return the number of bytes of payload for the entry that pCur is +@@ -71657,7 +75148,7 @@ SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){ + ** 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 datrabase. ++** corrupt database. + ** + ** The current implementation merely returns the size of the underlying + ** database file. +@@ -71957,7 +75448,6 @@ static int accessPayload( + assert( aWrite>=pBufStart ); /* due to (6) */ + memcpy(aSave, aWrite, 4); + rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); +- if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT; + nextPage = get4byte(aWrite); + memcpy(aWrite, aSave, 4); + }else +@@ -72119,8 +75609,7 @@ SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){ + ** vice-versa). + */ + static int moveToChild(BtCursor *pCur, u32 newPgno){ +- BtShared *pBt = pCur->pBt; +- ++ int rc; + assert( cursorOwnsBtShared(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage apPage[pCur->iPage] = pCur->pPage; + pCur->ix = 0; + pCur->iPage++; +- return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags); ++ 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 +@@ -72240,8 +75740,8 @@ static int moveToRoot(BtCursor *pCur){ + } + sqlite3BtreeClearCursor(pCur); + } +- rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage, +- 0, pCur->curPagerFlags); ++ rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage, ++ pCur->curPagerFlags); + if( rc!=SQLITE_OK ){ + pCur->eState = CURSOR_INVALID; + return rc; +@@ -72353,7 +75853,7 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ + *pRes = 0; + rc = moveToLeftmost(pCur); + }else if( rc==SQLITE_EMPTY ){ +- assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); ++ assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) ); + *pRes = 1; + rc = SQLITE_OK; + } +@@ -72364,9 +75864,25 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ + ** 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){ +- int rc; +- + assert( cursorOwnsBtShared(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + +@@ -72387,23 +75903,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ + *pRes = 0; + return SQLITE_OK; + } +- +- 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; ++ return btreeLast(pCur, pRes); + } + + /* Move the cursor so that it points to an entry in a table (a.k.a INTKEY) +@@ -72458,7 +75958,7 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( + /* 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 slowely */ ++ ** is still obtained without this case, only a little more slowly. */ + if( pCur->info.nKey+1==intKey ){ + *pRes = 0; + rc = sqlite3BtreeNext(pCur, 0); +@@ -72854,10 +76354,36 @@ bypass_moveto_root: + }else{ + chldPg = get4byte(findCell(pPage, lwr)); + } +- pCur->ix = (u16)lwr; +- rc = moveToChild(pCur, chldPg); +- if( rc ) break; +- } ++ ++ /* 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 ); +@@ -72948,14 +76474,8 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){ + + pPage = pCur->pPage; + idx = ++pCur->ix; +- if( !pPage->isInit || sqlite3FaultSim(412) ){ +- /* The only known way for this to happen is for there to be a +- ** recursive SQL function that does a DELETE operation as part of a +- ** SELECT which deletes content out from under an active cursor +- ** in a corrupt database file where the table being DELETE-ed from +- ** has pages in common with the table being queried. See TH3 +- ** module cov1/btree78.test testcase 220 (2018-06-08) for an +- ** example. */ ++ if( sqlite3FaultSim(412) ) pPage->isInit = 0; ++ if( !pPage->isInit ){ + return SQLITE_CORRUPT_BKPT; + } + +@@ -73047,7 +76567,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){ + } + + pPage = pCur->pPage; +- assert( pPage->isInit ); ++ 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))); +@@ -73131,8 +76654,8 @@ static int allocateBtreePage( + assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) ); + pPage1 = pBt->pPage1; + mxPage = btreePagecount(pBt); +- /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36 +- ** stores stores the total number of pages on the freelist. */ ++ /* 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 ){ +@@ -73218,7 +76741,7 @@ static int allocateBtreePage( + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + *ppPage = pTrunk; + pTrunk = 0; +- TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); ++ 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); +@@ -73284,7 +76807,7 @@ static int allocateBtreePage( + } + } + pTrunk = 0; +- TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); ++ TRACE(("ALLOCATE: %u trunk - %u free pages left\n", *pPgno, n-1)); + #endif + }else if( k>0 ){ + /* Extract a leaf from the trunk */ +@@ -73329,8 +76852,8 @@ static int allocateBtreePage( + ){ + int noContent; + *pPgno = iPage; +- TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" +- ": %d more free pages\n", ++ TRACE(("ALLOCATE: %u was leaf %u of %u on trunk %u" ++ ": %u more free pages\n", + *pPgno, closest+1, k, pTrunk->pgno, n-1)); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ) goto end_allocate_page; +@@ -73386,7 +76909,7 @@ static int allocateBtreePage( + ** becomes a new pointer-map page, the second is used by the caller. + */ + MemPage *pPg = 0; +- TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); ++ 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 ){ +@@ -73409,7 +76932,7 @@ static int allocateBtreePage( + releasePage(*ppPage); + *ppPage = 0; + } +- TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); ++ TRACE(("ALLOCATE: %u from end of file\n", *pPgno)); + } + + assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) ); +@@ -73477,7 +77000,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ + /* If the database supports auto-vacuum, write an entry in the pointer-map + ** to indicate that the page is free. + */ +- if( ISAUTOVACUUM ){ ++ if( ISAUTOVACUUM(pBt) ){ + ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0, &rc); + if( rc ) goto freepage_out; + } +@@ -73537,7 +77060,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ + } + rc = btreeSetHasContent(pBt, iPage); + } +- TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); ++ TRACE(("FREE-PAGE: %u leaf on trunk page %u\n",pPage->pgno,pTrunk->pgno)); + goto freepage_out; + } + } +@@ -73558,7 +77081,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ + put4byte(pPage->aData, iTrunk); + put4byte(&pPage->aData[4], 0); + put4byte(&pPage1->aData[32], iPage); +- TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk)); ++ TRACE(("FREE-PAGE: %u new trunk page replacing %u\n", pPage->pgno, iTrunk)); + + freepage_out: + if( pPage ){ +@@ -73647,7 +77170,7 @@ static SQLITE_NOINLINE int clearCellOverflow( + + /* 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. ++** Store the result code (SQLITE_OK or some error code) in rc. + ** + ** Implemented as macro to force inlining for performance. + */ +@@ -73881,12 +77404,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ + assert( pPage->pBt->usableSize > (u32)(ptr-data) ); + pc = get2byte(ptr); + hdr = pPage->hdrOffset; +-#if 0 /* Not required. Omit for efficiency */ +- if( pc nCell*2 ){ +- *pRC = SQLITE_CORRUPT_BKPT; +- return; +- } +-#endif + testcase( pc==(u32)get2byte(&data[hdr+5]) ); + testcase( pc+sz==pPage->pBt->usableSize ); + if( pc+sz > pPage->pBt->usableSize ){ +@@ -73924,23 +77441,27 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ + ** Allocating a new entry in pPage->aCell[] implies that + ** pPage->nOverflow is incremented. + ** +-** *pRC must be SQLITE_OK when this routine is called. ++** 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 void insertCell( ++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 *pRC /* Read and write return code from here */ ++ 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( *pRC==SQLITE_OK ); + assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); + assert( MX_CELL(pPage->pBt)<=10921 ); + assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); +@@ -73949,14 +77470,103 @@ static void insertCell( + 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; + } +- if( iChild ){ +- put4byte(pCell, iChild); ++ 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 +@@ -73975,31 +77585,20 @@ static void insertCell( + }else{ + int rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc!=SQLITE_OK ){ +- *pRC = rc; +- return; ++ return rc; + } + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + data = pPage->aData; + assert( &data[pPage->cellOffset]==pPage->aCellIdx ); + rc = allocateSpace(pPage, sz, &idx); +- if( rc ){ *pRC = rc; return; } ++ 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); +- if( iChild ){ +- /* 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); +- }else{ +- memcpy(&data[idx], pCell, sz); +- } ++ memcpy(&data[idx], pCell, sz); + pIns = pPage->aCellIdx + i*2; + memmove(pIns+2, pIns, 2*(pPage->nCell - i)); + put2byte(pIns, idx); +@@ -74009,13 +77608,16 @@ static void insertCell( + 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, pRC); ++ ptrmapPutOvflPtr(pPage, pPage, pCell, &rc2); ++ if( rc2 ) return rc2; + } + #endif + } ++ return SQLITE_OK; + } + + /* +@@ -74116,14 +77718,16 @@ struct CellArray { + ** 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( p->szCell[idx]==0 ){ +- p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]); ++ if( szCell[idx]==0 ){ ++ szCell[idx] = pRef->xCellSize(pRef, p->apCell[idx]); + }else{ + assert( CORRUPT_DB || +- p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) ); ++ szCell[idx]==pRef->xCellSize(pRef, p->apCell[idx]) ); + } + idx++; + N--; +@@ -74177,12 +77781,13 @@ static int rebuildPage( + 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); + +- for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k ixNx[k]<=i; k++){} + pSrcEnd = pCArray->apEnd[k]; + + pData = pEnd; +@@ -74245,7 +77850,7 @@ static int rebuildPage( + ** 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 accomodate all ++** 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( +@@ -74265,7 +77870,7 @@ static int pageInsertArray( + u8 *pEnd; /* Maximum extent of cell data */ + assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */ + if( iEnd<=iFirst ) return 0; +- for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k ixNx[k]<=i ; k++){} + pEnd = pCArray->apEnd[k]; + while( 1 /*Exit by break*/ ){ + int sz, rc; +@@ -74323,39 +77928,50 @@ static int pageFreeArray( + u8 * const pEnd = &aData[pPg->pBt->usableSize]; + u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; + int nRet = 0; +- int i; ++ int i, j; + int iEnd = iFirst + nCell; +- u8 *pFree = 0; +- int szFree = 0; ++ int nFree = 0; ++ int aOfst[10]; ++ int aAfter[10]; + + for(i=iFirst; i apCell[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 ); +- if( pFree!=(pCell + sz) ){ +- if( pFree ){ +- assert( pFree>aData && (pFree - aData)<65536 ); +- freeSpace(pPg, (u16)(pFree - aData), szFree); +- } +- pFree = pCell; +- szFree = sz; +- if( pFree+sz>pEnd ){ +- return 0; ++ iOfst = (u16)(pCell - aData); ++ iAfter = iOfst+sz; ++ for(j=0; j =nFree ){ ++ if( nFree>=(int)(sizeof(aOfst)/sizeof(aOfst[0])) ){ ++ for(j=0; j pEnd ) return 0; ++ nFree++; + } + nRet++; + } + } +- if( pFree ){ +- assert( pFree>aData && (pFree - aData)<65536 ); +- freeSpace(pPg, (u16)(pFree - aData), szFree); ++ for(j=0; j pPg->aDataEnd ) goto editpage_fail; ++ if( NEVER(pData>pPg->aDataEnd) ) goto editpage_fail; + + /* Add cells to the start of the page */ + if( iNew pgno, &rc); + if( szCell>pNew->minLocal ){ + ptrmapPutOvflPtr(pNew, pNew, pCell, &rc); +@@ -74582,8 +78199,8 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ + + /* Insert the new divider cell into pParent. */ + if( rc==SQLITE_OK ){ +- insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace), +- 0, pPage->pgno, &rc); ++ rc = insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace), ++ 0, pPage->pgno); + } + + /* Set the right-child pointer of pParent to point to the new page. */ +@@ -74692,7 +78309,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ + /* 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 ){ ++ if( ISAUTOVACUUM(pBt) ){ + *pRC = setChildPtrmaps(pTo); + } + } +@@ -74825,7 +78442,7 @@ static int balance_nonroot( + pgno = get4byte(pRight); + while( 1 ){ + if( rc==SQLITE_OK ){ +- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0); ++ rc = getAndInitPage(pBt, pgno, &apOld[i], 0); + } + if( rc ){ + memset(apOld, 0, (i+1)*sizeof(MemPage*)); +@@ -75116,15 +78733,17 @@ static int balance_nonroot( + d = r + 1 - leafData; + (void)cachedCellSize(&b, d); + do{ ++ int szR, szD; + assert( d szLeft-(b.szCell[r]+(i==k-1?0:2)))){ ++ && (bBulk || szRight+szD+2 > szLeft-(szR+(i==k-1?0:2)))){ + break; + } +- szRight += b.szCell[d] + 2; +- szLeft -= b.szCell[r] + 2; ++ szRight += szD + 2; ++ szLeft -= szR + 2; + cntNew[i-1] = r; + r--; + d--; +@@ -75137,7 +78756,7 @@ static int balance_nonroot( + } + } + +- /* Sanity check: For a non-corrupt database file one of the follwing ++ /* 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 +@@ -75145,7 +78764,7 @@ static int balance_nonroot( + ** that page. + */ + assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); +- TRACE(("BALANCE: old: %d(nc=%d) %d(nc=%d) %d(nc=%d)\n", ++ 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 +@@ -75178,7 +78797,7 @@ static int balance_nonroot( + cntOld[i] = b.nCell; + + /* Set the pointer-map entry for the new sibling page. */ +- if( ISAUTOVACUUM ){ ++ if( ISAUTOVACUUM(pBt) ){ + ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno, &rc); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; +@@ -75229,8 +78848,8 @@ static int balance_nonroot( + } + } + +- TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) " +- "%d(%d nc=%d) %d(%d nc=%d)\n", ++ 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, +@@ -75271,7 +78890,7 @@ static int balance_nonroot( + ** updated. This happens below, after the sibling pages have been + ** populated, not here. + */ +- if( ISAUTOVACUUM ){ ++ if( ISAUTOVACUUM(pBt) ){ + MemPage *pOld; + MemPage *pNew = pOld = apNew[0]; + int cntOldNext = pNew->nCell + pNew->nOverflow; +@@ -75362,13 +78981,13 @@ static int balance_nonroot( + iOvflSpace += sz; + assert( sz<=pBt->maxLocal+23 ); + assert( iOvflSpace <= (int)pBt->pageSize ); +- for(k=0; b.ixNx[k]<=j && ALWAYS(k pgno, &rc); ++ rc = insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno); + if( rc!=SQLITE_OK ) goto balance_cleanup; + assert( sqlite3PagerIswriteable(pParent->pDbPage) ); + } +@@ -75398,6 +79017,8 @@ static int balance_nonroot( + 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 */ +@@ -75464,7 +79085,7 @@ static int balance_nonroot( + ); + copyNodeContent(apNew[0], pParent, &rc); + freePage(apNew[0], &rc); +- }else if( ISAUTOVACUUM && !leafCorrection ){ ++ }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. */ +@@ -75475,7 +79096,7 @@ static int balance_nonroot( + } + + assert( pParent->isInit ); +- TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", ++ 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. +@@ -75485,7 +79106,7 @@ static int balance_nonroot( + } + + #if 0 +- if( ISAUTOVACUUM && rc==SQLITE_OK && apNew[0]->isInit ){ ++ if( ISAUTOVACUUM(pBt) && rc==SQLITE_OK && apNew[0]->isInit ){ + /* 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 +@@ -75547,7 +79168,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ + if( rc==SQLITE_OK ){ + rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0); + copyNodeContent(pRoot, pChild, &rc); +- if( ISAUTOVACUUM ){ ++ if( ISAUTOVACUUM(pBt) ){ + ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno, &rc); + } + } +@@ -75560,7 +79181,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); + +- TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); ++ 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, +@@ -75651,6 +79272,11 @@ static int balance(BtCursor *pCur){ + }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_BKPT; + }else{ + MemPage * const pParent = pCur->apPage[iPage-1]; + int const iIdx = pCur->aiIdx[iPage-1]; +@@ -75749,7 +79375,7 @@ static int btreeOverwriteContent( + ){ + int nData = pX->nData - iOffset; + if( nData<=0 ){ +- /* Overwritting with zeros */ ++ /* Overwriting with zeros */ + int i; + for(i=0; i pData to write */ + int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */ + int rc; /* Return code */ +@@ -75792,16 +79422,12 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ + Pgno ovflPgno; /* Next overflow page to write */ + u32 ovflPageSize; /* Size to write on overflow page */ + +- if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd +- || pCur->info.pPayload < pPage->aData + pPage->cellOffset +- ){ +- return SQLITE_CORRUPT_BKPT; +- } ++ assert( pCur->info.nLocal info.pPayload, pX, + 0, pCur->info.nLocal); + if( rc ) return rc; +- if( pCur->info.nLocal==nTotal ) return SQLITE_OK; + + /* Now overwrite the overflow pages */ + iOffset = pCur->info.nLocal; +@@ -75831,6 +79457,29 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ + return SQLITE_OK; + } + ++/* ++** Overwrite the cell that cursor pCur is pointing to with fresh content ++** contained in pX. ++*/ ++static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ ++ int nTotal = pX->nData + 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_BKPT; ++ } ++ 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 +@@ -75874,7 +79523,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + int idx; + MemPage *pPage; + Btree *p = pCur->pBtree; +- BtShared *pBt = p->pBt; + unsigned char *oldCell; + unsigned char *newCell = 0; + +@@ -75893,7 +79541,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + ** not to clear the cursor here. + */ + if( pCur->curFlags & BTCF_Multiple ){ +- rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); ++ 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 +@@ -75917,8 +79565,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + + assert( cursorOwnsBtShared(pCur) ); + assert( (pCur->curFlags & BTCF_WriteFlag)!=0 +- && pBt->inTransaction==TRANS_WRITE +- && (pBt->btsFlags & BTS_READ_ONLY)==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 +@@ -76016,7 +79664,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + } + } + assert( pCur->eState==CURSOR_VALID +- || (pCur->eState==CURSOR_INVALID && loc) ); ++ || (pCur->eState==CURSOR_INVALID && loc) || CORRUPT_DB ); + + pPage = pCur->pPage; + assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) ); +@@ -76031,31 +79679,34 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + if( rc ) return rc; + } + +- TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", ++ 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 = pBt->pTmpSpace; ++ newCell = p->pBt->pTmpSpace; + assert( newCell!=0 ); ++ assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); + if( flags & BTREE_PREFORMAT ){ + rc = SQLITE_OK; +- szNew = pBt->nPreformatSize; ++ szNew = p->pBt->nPreformatSize; + if( szNew<4 ) szNew = 4; +- if( ISAUTOVACUUM && szNew>pPage->maxLocal ){ ++ 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(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc); ++ 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; + } +- if( rc ) goto end_insert; + assert( szNew==pPage->xCellSize(pPage, newCell) ); +- assert( szNew <= MX_CELL_SIZE(pBt) ); ++ assert( szNew <= MX_CELL_SIZE(p->pBt) ); + idx = pCur->ix; ++ pCur->info.nSize = 0; + if( loc==0 ){ + CellInfo info; + assert( idx>=0 ); +@@ -76074,7 +79725,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + testcase( pCur->curFlags & BTCF_ValidOvfl ); + invalidateOverflowCache(pCur); + if( info.nSize==szNew && info.nLocal==info.nPayload +- && (!ISAUTOVACUUM || szNew minLocal) ++ && (!ISAUTOVACUUM(p->pBt) || szNew minLocal) + ){ + /* 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 +@@ -76104,7 +79755,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + }else{ + assert( pPage->leaf ); + } +- insertCell(pPage, idx, newCell, szNew, 0, 0, &rc); ++ rc = insertCellFast(pPage, idx, newCell, szNew); + assert( pPage->nOverflow==0 || rc==SQLITE_OK ); + assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); + +@@ -76128,7 +79779,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( + ** larger than the largest existing key, it is possible to insert the + ** row without seeking the cursor. This can be a big performance boost. + */ +- pCur->info.nSize = 0; + if( pPage->nOverflow ){ + assert( rc==SQLITE_OK ); + pCur->curFlags &= ~(BTCF_ValidNKey); +@@ -76177,7 +79827,6 @@ end_insert: + ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. + */ + SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){ +- int rc = SQLITE_OK; + BtShared *pBt = pDest->pBt; + u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */ + const u8 *aIn; /* Pointer to next input buffer */ +@@ -76200,7 +79849,9 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 + if( nIn==nRem && nIn pPage->maxLocal ){ + memcpy(aOut, aIn, nIn); + pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace); ++ return SQLITE_OK; + }else{ ++ int rc = SQLITE_OK; + Pager *pSrcPager = pSrc->pBt->pPager; + u8 *pPgnoOut = 0; + Pgno ovflIn = 0; +@@ -76252,7 +79903,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 + MemPage *pNew = 0; + rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); + put4byte(pPgnoOut, pgnoNew); +- if( ISAUTOVACUUM && pPageOut ){ ++ if( ISAUTOVACUUM(pBt) && pPageOut ){ + ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc); + } + releasePage(pPageOut); +@@ -76268,9 +79919,8 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 + + releasePage(pPageOut); + sqlite3PagerUnref(pPageIn); ++ return rc; + } +- +- return rc; + } + + /* +@@ -76329,6 +79979,9 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ + if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ + return SQLITE_CORRUPT_BKPT; + } ++ if( pCell<&pPage->aCellIdx[pPage->nCell] ){ ++ return SQLITE_CORRUPT_BKPT; ++ } + + /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must + ** be preserved following this delete operation. If the current delete +@@ -76425,7 +80078,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ + assert( pTmp!=0 ); + rc = sqlite3PagerWrite(pLeaf->pDbPage); + if( rc==SQLITE_OK ){ +- insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc); ++ rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n); + } + dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc); + if( rc ) return rc; +@@ -76505,7 +80158,7 @@ static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){ + MemPage *pRoot; + Pgno pgnoRoot; + int rc; +- int ptfFlags; /* Page-type flage for the root page of new table */ ++ int ptfFlags; /* Page-type flags for the root page of new table */ + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( pBt->inTransaction==TRANS_WRITE ); +@@ -76674,7 +80327,7 @@ static int clearDatabasePage( + if( pgno>btreePagecount(pBt) ){ + return SQLITE_CORRUPT_BKPT; + } +- rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); ++ rc = getAndInitPage(pBt, pgno, &pPage, 0); + if( rc ) return rc; + if( (pBt->openFlags & BTREE_SINGLE)==0 + && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) +@@ -77024,6 +80677,41 @@ SQLITE_PRIVATE Pager *sqlite3BtreePager(Btree *p){ + } + + #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. + */ +@@ -77033,6 +80721,7 @@ static void checkAppendMsg( + ... + ){ + va_list ap; ++ checkProgress(pCheck); + if( !pCheck->mxErr ) return; + pCheck->mxErr--; + pCheck->nErr++; +@@ -77041,12 +80730,13 @@ static void checkAppendMsg( + sqlite3_str_append(&pCheck->errMsg, "\n", 1); + } + if( pCheck->zPfx ){ +- sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); ++ 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 ){ +- pCheck->bOomFault = 1; ++ checkOom(pCheck); + } + } + #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +@@ -77058,7 +80748,8 @@ static void checkAppendMsg( + ** corresponds to page iPg is already set. + */ + static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ +- assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); ++ assert( pCheck->aPgRef!=0 ); ++ assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); + return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); + } + +@@ -77066,7 +80757,8 @@ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + ** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. + */ + static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ +- assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); ++ assert( pCheck->aPgRef!=0 ); ++ assert( iPg<=pCheck->nCkPage && sizeof(pCheck->aPgRef[0])==1 ); + pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); + } + +@@ -77080,15 +80772,14 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + ** Also check that the page number is in bounds. + */ + static int checkRef(IntegrityCk *pCheck, Pgno iPage){ +- if( iPage>pCheck->nPage || iPage==0 ){ +- checkAppendMsg(pCheck, "invalid page number %d", 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 %d", iPage); ++ checkAppendMsg(pCheck, "2nd reference to page %u", iPage); + return 1; + } +- if( AtomicLoad(&pCheck->db->u1.isInterrupted) ) return 1; + setPageReferenced(pCheck, iPage); + return 0; + } +@@ -77111,14 +80802,14 @@ static void checkPtrmap( + + rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); + if( rc!=SQLITE_OK ){ +- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->bOomFault = 1; +- checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild); ++ 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=%d expected=(%d,%d) got=(%d,%d)", ++ "Bad ptr map entry key=%u expected=(%u,%u) got=(%u,%u)", + iChild, eType, iParent, ePtrmapType, iPtrmapParent); + } + } +@@ -77143,7 +80834,7 @@ static void checkList( + if( checkRef(pCheck, iPage) ) break; + N--; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ +- checkAppendMsg(pCheck, "failed to get page %d", iPage); ++ checkAppendMsg(pCheck, "failed to get page %u", iPage); + break; + } + pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); +@@ -77156,7 +80847,7 @@ static void checkList( + #endif + if( n>pCheck->pBt->usableSize/4-2 ){ + checkAppendMsg(pCheck, +- "freelist leaf count too big on page %d", iPage); ++ "freelist leaf count too big on page %u", iPage); + N--; + }else{ + for(i=0; i<(int)n; i++){ +@@ -77188,7 +80879,7 @@ static void checkList( + } + if( N && nErrAtStart==pCheck->nErr ){ + checkAppendMsg(pCheck, +- "%s is %d but should be %d", ++ "%s is %u but should be %u", + isFreeList ? "size" : "overflow list length", + expected-N, expected); + } +@@ -77218,7 +80909,9 @@ static void checkList( + ** lower 16 bits are the index of the last byte of that range. + */ + static void btreeHeapInsert(u32 *aHeap, u32 x){ +- u32 j, i = ++aHeap[0]; ++ u32 j, i; ++ assert( aHeap!=0 ); ++ i = ++aHeap[0]; + aHeap[i] = x; + while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ + x = aHeap[j]; +@@ -77295,15 +80988,18 @@ static int checkTreePage( + + /* 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 = "Page %u: "; ++ 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; + } + +@@ -77326,7 +81022,7 @@ static int checkTreePage( + hdr = pPage->hdrOffset; + + /* Set up for cell analysis */ +- pCheck->zPfx = "On tree page %u cell %d: "; ++ pCheck->zPfx = "Tree %u page %u cell %u: "; + contentOffset = get2byteNotZero(&data[hdr+5]); + assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ + +@@ -77346,7 +81042,7 @@ static int checkTreePage( + pgno = get4byte(&data[hdr+8]); + #ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ +- pCheck->zPfx = "On page %u at right child: "; ++ pCheck->zPfx = "Tree %u page %u right child: "; + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); + } + #endif +@@ -77370,7 +81066,7 @@ static int checkTreePage( + pc = get2byteAligned(pCellIdx); + pCellIdx -= 2; + if( pc usableSize-4 ){ +- checkAppendMsg(pCheck, "Offset %d out of range %d..%d", ++ checkAppendMsg(pCheck, "Offset %u out of range %u..%u", + pc, contentOffset, usableSize-4); + doCoverageCheck = 0; + continue; +@@ -77502,7 +81198,7 @@ static int checkTreePage( + */ + if( heap[0]==0 && nFrag!=data[hdr+7] ){ + checkAppendMsg(pCheck, +- "Fragmentation of %d bytes reported as %d on page %u", ++ "Fragmentation of %u bytes reported as %u on page %u", + nFrag, data[hdr+7], iPage); + } + } +@@ -77540,13 +81236,14 @@ end_of_check: + ** the unverified btrees. Except, if aRoot[1] is 1, then the freelist + ** checks are still performed. + */ +-SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( ++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 */ + int nRoot, /* Number of entries in aRoot[] */ + int mxErr, /* Stop reporting errors after this many */ +- int *pnErr /* Write number of errors seen to this variable */ ++ int *pnErr, /* OUT: Write number of errors seen to this variable */ ++ char **pzOut /* OUT: Write the error message string here */ + ){ + Pgno i; + IntegrityCk sCheck; +@@ -77569,42 +81266,36 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + 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.nPage = btreePagecount(sCheck.pBt); ++ sCheck.nCkPage = btreePagecount(sCheck.pBt); + sCheck.mxErr = mxErr; +- sCheck.nErr = 0; +- sCheck.bOomFault = 0; +- sCheck.zPfx = 0; +- sCheck.v1 = 0; +- sCheck.v2 = 0; +- sCheck.aPgRef = 0; +- sCheck.heap = 0; + sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); + sCheck.errMsg.printfFlags = SQLITE_PRINTF_INTERNAL; +- if( sCheck.nPage==0 ){ ++ if( sCheck.nCkPage==0 ){ + goto integrity_ck_cleanup; + } + +- sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); ++ sCheck.aPgRef = sqlite3MallocZero((sCheck.nCkPage / 8)+ 1); + if( !sCheck.aPgRef ){ +- sCheck.bOomFault = 1; ++ checkOom(&sCheck); + goto integrity_ck_cleanup; + } + sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); + if( sCheck.heap==0 ){ +- sCheck.bOomFault = 1; ++ checkOom(&sCheck); + goto integrity_ck_cleanup; + } + + i = PENDING_BYTE_PAGE(pBt); +- if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); ++ if( i<=sCheck.nCkPage ) setPageReferenced(&sCheck, i); + + /* Check the integrity of the freelist + */ + if( bCkFreelist ){ +- sCheck.zPfx = "Main freelist: "; ++ sCheck.zPfx = "Freelist: "; + checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), + get4byte(&pBt->pPage1->aData[36])); + sCheck.zPfx = 0; +@@ -77621,7 +81312,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + mxInHdr = get4byte(&pBt->pPage1->aData[52]); + if( mx!=mxInHdr ){ + checkAppendMsg(&sCheck, +- "max rootpage (%d) disagrees with header (%d)", ++ "max rootpage (%u) disagrees with header (%u)", + mx, mxInHdr + ); + } +@@ -77642,6 +81333,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0); + } + #endif ++ sCheck.v0 = aRoot[i]; + checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64); + } + pBt->db->flags = savedDbFlags; +@@ -77649,10 +81341,10 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + /* Make sure every page in the file is referenced + */ + if( !bPartial ){ +- for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ ++ for(i=1; i<=sCheck.nCkPage && sCheck.mxErr; i++){ + #ifdef SQLITE_OMIT_AUTOVACUUM + if( getPageReferenced(&sCheck, i)==0 ){ +- checkAppendMsg(&sCheck, "Page %d is never used", i); ++ checkAppendMsg(&sCheck, "Page %u: never used", i); + } + #else + /* If the database supports auto-vacuum, make sure no tables contain +@@ -77660,11 +81352,11 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + */ + if( getPageReferenced(&sCheck, i)==0 && + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ +- checkAppendMsg(&sCheck, "Page %d is never used", i); ++ checkAppendMsg(&sCheck, "Page %u: never used", i); + } + if( getPageReferenced(&sCheck, i)!=0 && + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ +- checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i); ++ checkAppendMsg(&sCheck, "Page %u: pointer map referenced", i); + } + #endif + } +@@ -77675,16 +81367,17 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( + integrity_ck_cleanup: + sqlite3PageFree(sCheck.heap); + sqlite3_free(sCheck.aPgRef); +- if( sCheck.bOomFault ){ ++ *pnErr = sCheck.nErr; ++ if( sCheck.nErr==0 ){ + sqlite3_str_reset(&sCheck.errMsg); +- sCheck.nErr++; ++ *pzOut = 0; ++ }else{ ++ *pzOut = sqlite3StrAccumFinish(&sCheck.errMsg); + } +- *pnErr = sCheck.nErr; +- if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg); + /* Make sure this analysis did not leave any unref() pages. */ + assert( nRef==sqlite3PagerRefcount(pBt->pPager) ); + sqlite3BtreeLeave(p); +- return sqlite3StrAccumFinish(&sCheck.errMsg); ++ return sCheck.rc; + } + #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +@@ -77949,6 +81642,17 @@ SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *p){ + */ + 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. +@@ -78214,13 +81918,7 @@ static int backupOnePage( + assert( !isFatalError(p->rc) ); + assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); + assert( zSrcData ); +- +- /* Catch the case where the destination is an in-memory database and the +- ** page sizes of the source and destination differ. +- */ +- if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ +- rc = SQLITE_READONLY; +- } ++ assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 ); + + /* This loop runs once for each destination page spanned by the source + ** page. For each iteration, variable iOff is set to the byte offset +@@ -78353,7 +82051,10 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ + pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); + pgszDest = sqlite3BtreeGetPageSize(p->pDest); + destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); +- if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ ++ if( SQLITE_OK==rc ++ && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager)) ++ && pgszSrc!=pgszDest ++ ){ + rc = SQLITE_READONLY; + } + +@@ -78859,9 +82560,9 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ + i64 x; + assert( (p->flags&MEM_Int)*2==sizeof(x) ); + memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2); +- sqlite3Int64ToText(x, zBuf); ++ p->n = sqlite3Int64ToText(x, zBuf); + #else +- sqlite3Int64ToText(p->u.i, zBuf); ++ p->n = sqlite3Int64ToText(p->u.i, zBuf); + #endif + }else{ + sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0); +@@ -78869,6 +82570,7 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ + (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; + } + } + +@@ -78896,10 +82598,12 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ + ** 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 */ +@@ -78912,7 +82616,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){ + 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; +- vdbeMemRenderNum(sizeof(zBuf), zBuf, p); ++ memcpy(&tmp, p, sizeof(tmp)); ++ vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp); + z = p->z; + i = j = 0; + incr = 1; +@@ -79055,6 +82760,40 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ + 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; ++ if( NEVER(pMem->z==0) ) return; ++ 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. +@@ -79181,7 +82920,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){ + + vdbeMemRenderNum(nByte, pMem->z, pMem); + assert( pMem->z!=0 ); +- pMem->n = sqlite3Strlen30NN(pMem->z); ++ 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); +@@ -79316,36 +83055,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){ + if( p->szMalloc ) vdbeMemClear(p); + } + +-/* +-** Convert a 64-bit IEEE double into a 64-bit signed integer. +-** If the double is out of range of a 64-bit signed integer then +-** return the closest available 64-bit signed integer. +-*/ +-static SQLITE_NOINLINE i64 doubleToInt64(double r){ +-#ifdef SQLITE_OMIT_FLOATING_POINT +- /* When floating-point is omitted, double and int64 are the same thing */ +- return r; +-#else +- /* +- ** Many compilers we encounter do not define constants for the +- ** minimum and maximum 64-bit integers, or they define them +- ** inconsistently. And many do not understand the "LL" notation. +- ** So we define our own static constants here using nothing +- ** larger than a 32-bit integer constant. +- */ +- static const i64 maxInt = LARGEST_INT64; +- static const i64 minInt = SMALLEST_INT64; +- +- if( r<=(double)minInt ){ +- return minInt; +- }else if( r>=(double)maxInt ){ +- return maxInt; +- }else{ +- return (i64)r; +- } +-#endif +-} +- + /* + ** Return some kind of integer value which is the best we can do + ** at representing the value that *pMem describes as an integer. +@@ -79372,7 +83081,7 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ + testcase( flags & MEM_IntReal ); + return pMem->u.i; + }else if( flags & MEM_Real ){ +- return doubleToInt64(pMem->u.r); ++ return sqlite3RealToI64(pMem->u.r); + }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){ + return memIntValue(pMem); + }else{ +@@ -79421,32 +83130,35 @@ SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ + } + + /* +-** The MEM structure is already a MEM_Real. Try to also make it a +-** MEM_Int if we can. ++** 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){ +- i64 ix; + assert( pMem!=0 ); +- assert( pMem->flags & MEM_Real ); ++ 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) ); + +- ix = doubleToInt64(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 && ix u.i = ix; ++ 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 && ix u.i = ix; ++ MemSetTypeFlag(pMem, MEM_Int); ++ } + } + } + +@@ -79494,6 +83206,16 @@ SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ + && 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. +@@ -79515,7 +83237,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ + 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 = (i64)pMem->u.r)) ++ || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r))) + ){ + pMem->u.i = ix; + MemSetTypeFlag(pMem, MEM_Int); +@@ -79561,13 +83283,17 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){ + 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); +- return sqlite3VdbeChangeEncoding(pMem, encoding); ++ if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1; ++ rc = sqlite3VdbeChangeEncoding(pMem, encoding); ++ if( rc ) return rc; ++ sqlite3VdbeMemZeroTerminateIfAble(pMem); + } + } + return SQLITE_OK; +@@ -80091,6 +83817,24 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ + 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. + */ +@@ -80158,6 +83902,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ + } + + pRec->nField = p->iVal+1; ++ sqlite3VdbeMemSetNull(&pRec->aMem[p->iVal]); + return &pRec->aMem[p->iVal]; + } + #else +@@ -80211,9 +83956,12 @@ static int valueFromFunction( + 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) ++ || (pFunc->funcFlags & (SQLITE_FUNC_NEEDCOLL|SQLITE_FUNC_RUNONLY))!=0 + ){ + return SQLITE_OK; + } +@@ -80236,8 +83984,6 @@ static int valueFromFunction( + goto value_from_function_out; + } + +- testcase( pCtx->pParse->rc==SQLITE_ERROR ); +- testcase( pCtx->pParse->rc==SQLITE_OK ); + memset(&ctx, 0, sizeof(ctx)); + ctx.pOut = pVal; + ctx.pFunc = pFunc; +@@ -80250,16 +83996,16 @@ static int valueFromFunction( + sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); + assert( rc==SQLITE_OK ); + rc = sqlite3VdbeChangeEncoding(pVal, enc); +- if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ ++ if( NEVER(rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal)) ){ + rc = SQLITE_TOOBIG; + pCtx->pParse->nErr++; + } + } +- pCtx->pParse->rc = rc; + + value_from_function_out: + if( rc!=SQLITE_OK ){ + pVal = 0; ++ pCtx->pParse->rc = rc; + } + if( apVal ){ + for(i=0; i 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); + } +@@ -80409,6 +84162,7 @@ static int valueFromExpr( + if( pVal ){ + pVal->flags = MEM_Int; + pVal->u.i = pExpr->u.zToken[4]==0; ++ sqlite3ValueApplyAffinity(pVal, affinity, enc); + } + } + +@@ -80702,6 +84456,9 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ + 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; +@@ -80747,10 +84504,10 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ + memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp)); + p->db = db; + if( db->pVdbe ){ +- db->pVdbe->pPrev = p; ++ db->pVdbe->ppVPrev = &p->pVNext; + } +- p->pNext = db->pVdbe; +- p->pPrev = 0; ++ p->pVNext = db->pVdbe; ++ p->ppVPrev = &db->pVdbe; + db->pVdbe = p; + assert( p->eVdbeState==VDBE_INIT_STATE ); + p->pParse = pParse; +@@ -80832,21 +84589,28 @@ SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString( + #endif + + /* +-** Swap all content between two VDBE structures. ++** 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; ++ Vdbe tmp, *pTmp, **ppTmp; + char *zTmp; + assert( pA->db==pB->db ); + tmp = *pA; + *pA = *pB; + *pB = tmp; +- pTmp = pA->pNext; +- pA->pNext = pB->pNext; +- pB->pNext = pTmp; +- pTmp = pA->pPrev; +- pA->pPrev = pB->pPrev; +- pB->pPrev = pTmp; ++ 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; +@@ -80921,11 +84685,43 @@ static int growOpArray(Vdbe *v, int nOp){ + ** sqlite3CantopenError(lineno) + */ + static void test_addop_breakpoint(int pc, Op *pOp){ +- static int n = 0; ++ 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. +@@ -80936,17 +84732,16 @@ static void test_addop_breakpoint(int pc, Op *pOp){ + ** + ** op The opcode for this instruction + ** +-** p1, p2, p3 Operands +-** +-** Use the sqlite3VdbeResolveLabel() function to fix an address and +-** the sqlite3VdbeChangeP4() function to change the value of the P4 +-** operand. ++** p1, p2, p3, p4 Operands + */ +-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); ++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; +@@ -80969,32 +84764,78 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ + pOp->p3 = p3; + pOp->p4.p = 0; + pOp->p4type = P4_NOTUSED; ++ ++ /* 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 VDBE_PROFILE +- pOp->cycles = 0; +- pOp->cnt = 0; +-#endif + #ifdef SQLITE_VDBE_COVERAGE + pOp->iSrcLine = 0; + #endif ++ /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ ** Replicate in sqlite3VdbeAddOp4Int() */ ++ + return i; + } +-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 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 +@@ -81149,11 +84990,12 @@ SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char *z1, const char *z2){ + ** If the bPush flag is true, then make this opcode the parent for + ** subsequent Explains until sqlite3VdbeExplainPop() is called. + */ +-SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ +-#ifndef SQLITE_DEBUG ++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 ) ++ if( pParse->explain==2 || IS_STMT_SCANSTATUS(pParse->db) ) + #endif + { + char *zMsg; +@@ -81165,13 +85007,15 @@ SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt + va_end(ap); + v = pParse->pVdbe; + iThis = v->nOp; +- sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, ++ addr = sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0, + zMsg, P4_DYNAMIC); +- sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetOp(v,-1)->p4.z); ++ sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetLastOp(v)->p4.z); + if( bPush){ + pParse->addrExplain = iThis; + } ++ sqlite3VdbeScanStatus(v, iThis, -1, -1, 0, 0); + } ++ return addr; + } + + /* +@@ -81199,26 +85043,6 @@ SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, + sqlite3MayAbort(p->pParse); + } + +-/* +-** Add an opcode that includes the p4 value as an integer. +-*/ +-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 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; +-} +- + /* Insert the end of a co-routine + */ + SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){ +@@ -81279,6 +85103,9 @@ static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){ + int i; + for(i=p->nLabelAlloc; i aLabel[i] = -1; + #endif ++ if( nNewSize>=100 && (nNewSize/100)>(p->nLabelAlloc/100) ){ ++ sqlite3ProgressCheck(p); ++ } + p->nLabelAlloc = nNewSize; + p->aLabel[j] = v->nOp; + } +@@ -81522,11 +85349,13 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ + 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]; +- while(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 +@@ -81555,6 +85384,10 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ + 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>nMaxArgs ) nMaxArgs = pOp->p2; +@@ -81577,6 +85410,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ + ** 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)]; + } + break; +@@ -81587,11 +85421,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ + ** have non-negative values for P2. */ + assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0); + } +- if( pOp==p->aOp ) break; ++ assert( pOp>p->aOp ); + pOp--; + } ++resolve_p2_values_loop_exit: + if( aLabel ){ +- sqlite3DbFreeNN(p->db, pParse->aLabel); ++ sqlite3DbNNFreeNN(p->db, pParse->aLabel); + pParse->aLabel = 0; + } + pParse->nLabel = 0; +@@ -81642,6 +85477,10 @@ SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn( + 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 ); +@@ -81819,20 +85658,83 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus( + LogEst nEst, /* Estimated number of output rows */ + const char *zName /* Name of table or index being scanned */ + ){ +- sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus); +- ScanStatus *aNew; +- aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); +- if( aNew ){ +- ScanStatus *pNew = &aNew[p->nScan++]; +- pNew->addrExplain = addrExplain; +- pNew->addrLoop = addrLoop; +- pNew->addrVisit = addrVisit; +- pNew->nEst = nEst; +- pNew->zName = sqlite3DbStrDup(p->db, zName); +- p->aScan = aNew; ++ if( IS_STMT_SCANSTATUS(p->db) ){ ++ sqlite3_int64 nByte = (p->nScan+1) * 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; ++ } + } + } +-#endif ++ ++/* ++** 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; ii aAddrRange); 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) */ + + + /* +@@ -81840,15 +85742,19 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus( + ** 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){ +@@ -81856,6 +85762,18 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ + 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); ++ 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. +@@ -81884,7 +85802,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ + || p->aOp[addr].opcode==OP_FkIfZero ); + assert( p->aOp[addr].p4type==0 ); + #ifdef SQLITE_VDBE_COVERAGE +- sqlite3VdbeGetOp(p,-1)->iSrcLine = 0; /* Erase VdbeCoverage() macros */ ++ sqlite3VdbeGetLastOp(p)->iSrcLine = 0; /* Erase VdbeCoverage() macros */ + #endif + p->nOp--; + }else{ +@@ -81895,11 +85813,12 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ + + /* + ** If the input FuncDef structure is ephemeral, then free it. If +-** the FuncDef is not ephermal, then do nothing. ++** 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 ){ +- sqlite3DbFreeNN(db, pDef); ++ sqlite3DbNNFreeNN(db, pDef); + } + } + +@@ -81908,11 +85827,12 @@ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){ + */ + static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){ + if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc); +- sqlite3DbFreeNN(db, p); ++ sqlite3DbNNFreeNN(db, p); + } + static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){ ++ assert( db!=0 ); + freeEphemeralFunction(db, p->pFunc); +- sqlite3DbFreeNN(db, p); ++ sqlite3DbNNFreeNN(db, p); + } + static void freeP4(sqlite3 *db, int p4type, void *p4){ + assert( db ); +@@ -81925,7 +85845,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ + case P4_INT64: + case P4_DYNAMIC: + case P4_INTARRAY: { +- sqlite3DbFree(db, p4); ++ if( p4 ) sqlite3DbNNFreeNN(db, p4); + break; + } + case P4_KEYINFO: { +@@ -81954,6 +85874,10 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ + if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4); + break; + } ++ case P4_TABLEREF: { ++ if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4); ++ break; ++ } + } + } + +@@ -81964,6 +85888,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ + */ + 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 */ +@@ -81974,7 +85899,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ + if( pOp==aOp ) break; + pOp--; + } +- sqlite3DbFreeNN(db, aOp); ++ sqlite3DbNNFreeNN(db, aOp); + } + } + +@@ -82056,7 +85981,6 @@ SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters( + } + #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 +@@ -82081,7 +86005,7 @@ static void SQLITE_NOINLINE vdbeChangeP4Full( + int n + ){ + if( pOp->p4type ){ +- freeP4(p->db, pOp->p4type, pOp->p4.p); ++ assert( pOp->p4type > P4_FREE_IF_LE ); + pOp->p4type = 0; + pOp->p4.p = 0; + } +@@ -82143,7 +86067,7 @@ SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){ + if( p->db->mallocFailed ){ + freeP4(p->db, n, pP4); + }else{ +- assert( pP4!=0 ); ++ assert( pP4!=0 || n==P4_DYNAMIC ); + assert( p->nOp>0 ); + pOp = &p->aOp[p->nOp-1]; + assert( pOp->p4type==P4_NOTUSED ); +@@ -82205,13 +86129,13 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ + ** Set the value if the iSrcLine field for the previously coded instruction. + */ + SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){ +- sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine; ++ sqlite3VdbeGetLastOp(v)->iSrcLine = iLine; + } + #endif /* SQLITE_VDBE_COVERAGE */ + + /* +-** Return the opcode for a given address. If the address is -1, then +-** return the most recently inserted opcode. ++** 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 +@@ -82227,9 +86151,6 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ + ** 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 ); +- if( addr<0 ){ +- addr = p->nOp - 1; +- } + assert( (addr>=0 && addr nOp) || p->db->mallocFailed ); + if( p->db->mallocFailed ){ + return (VdbeOp*)&dummy; +@@ -82238,6 +86159,12 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int 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 +@@ -82725,7 +86652,7 @@ static void releaseMemArray(Mem *p, int N){ + sqlite3VdbeMemRelease(p); + p->flags = MEM_Undefined; + }else if( p->szMalloc ){ +- sqlite3DbFreeNN(db, p->zMalloc); ++ sqlite3DbNNFreeNN(db, p->zMalloc); + p->szMalloc = 0; + p->flags = MEM_Undefined; + } +@@ -82939,7 +86866,6 @@ SQLITE_PRIVATE int sqlite3VdbeList( + ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. + */ + releaseMemArray(pMem, 8); +- p->pResultSet = 0; + + if( p->rc==SQLITE_NOMEM ){ + /* This happens if a malloc() inside a call to sqlite3_column_text() or +@@ -82975,7 +86901,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( + sqlite3VdbeMemSetInt64(pMem+1, pOp->p2); + sqlite3VdbeMemSetInt64(pMem+2, pOp->p3); + sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free); +- p->nResColumn = 4; ++ assert( p->nResColumn==4 ); + }else{ + sqlite3VdbeMemSetInt64(pMem+0, i); + sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode), +@@ -82994,9 +86920,9 @@ SQLITE_PRIVATE int sqlite3VdbeList( + sqlite3VdbeMemSetNull(pMem+7); + #endif + sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free); +- p->nResColumn = 8; ++ assert( p->nResColumn==8 ); + } +- p->pResultSet = pMem; ++ p->pResultRow = pMem; + if( db->mallocFailed ){ + p->rc = SQLITE_NOMEM; + rc = SQLITE_ERROR; +@@ -83107,7 +87033,7 @@ static void *allocSpace( + ** running it. + */ + SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ +-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) ++#if defined(SQLITE_DEBUG) + int i; + #endif + assert( p!=0 ); +@@ -83136,8 +87062,8 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ + p->nFkConstraint = 0; + #ifdef VDBE_PROFILE + for(i=0; i nOp; i++){ +- p->aOp[i].cnt = 0; +- p->aOp[i].cycles = 0; ++ p->aOp[i].nExec = 0; ++ p->aOp[i].nCycle = 0; + } + #endif + } +@@ -83208,26 +87134,9 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( + resolveP2Values(p, &nArg); + p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); + if( pParse->explain ){ +- static const char * const azColName[] = { +- "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", +- "id", "parent", "notused", "detail" +- }; +- int iFirst, mx, i; + if( nMem<10 ) nMem = 10; + p->explain = pParse->explain; +- if( pParse->explain==2 ){ +- sqlite3VdbeSetNumCols(p, 4); +- iFirst = 8; +- mx = 12; +- }else{ +- sqlite3VdbeSetNumCols(p, 8); +- iFirst = 0; +- mx = 8; +- } +- for(i=iFirst; i nResColumn = 12 - 4*p->explain; + } + p->expired = 0; + +@@ -83246,9 +87155,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( + p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem)); + p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*)); + p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*)); +-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- p->anExec = allocSpace(&x, 0, p->nOp*sizeof(i64)); +-#endif + if( x.nNeeded ){ + x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); + x.nFree = x.nNeeded; +@@ -83257,9 +87163,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( + 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_ENABLE_STMT_SCANSTATUS +- p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64)); +-#endif + } + } + +@@ -83274,9 +87177,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( + p->nMem = nMem; + initMemArray(p->aMem, nMem, db, MEM_Undefined); + memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*)); +-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- memset(p->anExec, 0, p->nOp*sizeof(i64)); +-#endif + } + sqlite3VdbeRewind(p); + } +@@ -83288,7 +87188,23 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( + 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); +@@ -83334,9 +87250,6 @@ static void closeCursorsInFrame(Vdbe *p){ + SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ + Vdbe *v = pFrame->v; + closeCursorsInFrame(v); +-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- v->anExec = pFrame->anExec; +-#endif + v->aOp = pFrame->aOp; + v->nOp = pFrame->nOp; + v->aMem = pFrame->aMem; +@@ -83392,12 +87305,12 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ + int n; + sqlite3 *db = p->db; + +- if( p->nResColumn ){ +- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); ++ if( p->nResAlloc ){ ++ releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); + sqlite3DbFree(db, p->aColName); + } + n = nResColumn*COLNAME_N; +- p->nResColumn = (u16)nResColumn; ++ 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); +@@ -83422,14 +87335,14 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName( + ){ + int rc; + Mem *pColName; +- assert( idx nResColumn ); ++ assert( idx nResAlloc ); + assert( var db->mallocFailed ){ + assert( !zName || xDel!=SQLITE_DYNAMIC ); + return SQLITE_NOMEM_BKPT; + } + assert( p->aColName!=0 ); +- pColName = &(p->aColName[idx+var*p->nResColumn]); ++ 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; +@@ -83717,7 +87630,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){ + if( p->readOnly==0 ) nWrite++; + if( p->bIsReader ) nRead++; + } +- p = p->pNext; ++ p = p->pVNext; + } + assert( cnt==db->nVdbeActive ); + assert( nWrite==db->nVdbeWrite ); +@@ -83942,6 +87855,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ + sqlite3VdbeLeave(p); + return SQLITE_BUSY; + }else if( rc!=SQLITE_OK ){ ++ sqlite3SystemError(db, rc); + p->rc = rc; + sqlite3RollbackAll(db, SQLITE_OK); + p->nChange = 0; +@@ -83951,6 +87865,8 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ + 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; +@@ -84140,7 +88056,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + } +- p->pResultSet = 0; ++ p->pResultRow = 0; + #ifdef SQLITE_DEBUG + p->nWrite = 0; + #endif +@@ -84168,10 +88084,12 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ + } + for(i=0; i nOp; i++){ + char zHdr[100]; ++ i64 cnt = p->aOp[i].nExec; ++ i64 cycles = p->aOp[i].nCycle; + sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ", +- p->aOp[i].cnt, +- p->aOp[i].cycles, +- p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0 ++ cnt, ++ cycles, ++ cnt>0 ? cycles/cnt : 0 + ); + fprintf(out, "%s", zHdr); + sqlite3VdbePrintOp(out, i, &p->aOp[i]); +@@ -84246,10 +88164,11 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, + */ + 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->nResColumn*COLNAME_N); +- sqlite3DbFreeNN(db, p->aColName); ++ releaseMemArray(p->aColName, p->nResAlloc*COLNAME_N); ++ sqlite3DbNNFreeNN(db, p->aColName); + } + for(pSub=p->pProgram; pSub; pSub=pNext){ + pNext = pSub->pNext; +@@ -84258,17 +88177,17 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ + } + if( p->eVdbeState!=VDBE_INIT_STATE ){ + releaseMemArray(p->aVar, p->nVar); +- if( p->pVList ) sqlite3DbFreeNN(db, p->pVList); +- if( p->pFree ) sqlite3DbFreeNN(db, p->pFree); ++ if( p->pVList ) sqlite3DbNNFreeNN(db, p->pVList); ++ if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree); + } + vdbeFreeOpArray(db, p->aOp, p->nOp); +- sqlite3DbFree(db, p->zSql); ++ if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql); + #ifdef SQLITE_ENABLE_NORMALIZE + sqlite3DbFree(db, p->zNormSql); + { +- DblquoteStr *pThis, *pNext; +- for(pThis=p->pDblStr; pThis; pThis=pNext){ +- pNext = pThis->pNextStr; ++ DblquoteStr *pThis, *pNxt; ++ for(pThis=p->pDblStr; pThis; pThis=pNxt){ ++ pNxt = pThis->pNextStr; + sqlite3DbFree(db, pThis); + } + } +@@ -84292,20 +88211,17 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ + + assert( p!=0 ); + db = p->db; ++ assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + sqlite3VdbeClearObject(db, p); + if( db->pnBytesFreed==0 ){ +- if( p->pPrev ){ +- p->pPrev->pNext = p->pNext; +- }else{ +- assert( db->pVdbe==p ); +- db->pVdbe = p->pNext; +- } +- if( p->pNext ){ +- p->pNext->pPrev = p->pPrev; ++ assert( p->ppVPrev!=0 ); ++ *p->ppVPrev = p->pVNext; ++ if( p->pVNext ){ ++ p->pVNext->ppVPrev = p->ppVPrev; + } + } +- sqlite3DbFreeNN(db, p); ++ sqlite3DbNNFreeNN(db, p); + } + + /* +@@ -84851,6 +88767,15 @@ static int vdbeRecordCompareDebug( + 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; + } + +@@ -85019,20 +88944,33 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem + 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 a8 ){ ++ if( sqlite3IsNaN(r) ){ ++ /* SQLite considers NaN to be a NULL. And all integer values are greater ++ ** than NULL */ ++ return 1; ++ } ++ if( sqlite3Config.bUseLongDouble ){ + LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i; + testcase( x r ); + testcase( x==r ); +- if( x r ) return +1; /*NO_TEST*/ /* work around bugs in gcov */ +- return 0; /*NO_TEST*/ /* work around bugs in gcov */ ++ return (x r); + }else{ + i64 y; + double s; +@@ -85042,9 +88980,10 @@ SQLITE_PRIVATE int sqlite3IntFloatCompare(i64 i, double r){ + if( i y ) return +1; + s = (double)i; +- if( s r ) return +1; +- return 0; ++ testcase( doubleLt(s,r) ); ++ testcase( doubleLt(r,s) ); ++ testcase( doubleEq(r,s) ); ++ return (s r); + } + } + +@@ -85260,7 +89199,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( + assert( pPKey2->pKeyInfo->aSortFlags!=0 ); + assert( pPKey2->pKeyInfo->nKeyField>0 ); + assert( idx1<=szHdr1 || CORRUPT_DB ); +- do{ ++ while( 1 /*exit-by-break*/ ){ + u32 serial_type; + + /* RHS is an integer */ +@@ -85270,7 +89209,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( + serial_type = aKey1[idx1]; + testcase( serial_type==12 ); + if( serial_type>=10 ){ +- rc = +1; ++ rc = serial_type==10 ? -1 : +1; + }else if( serial_type==0 ){ + rc = -1; + }else if( serial_type==7 ){ +@@ -85294,8 +89233,8 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( + /* 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 numberic values are. */ +- rc = +1; ++ ** them to numeric values are. */ ++ rc = serial_type==10 ? -1 : +1; + }else if( serial_type==0 ){ + rc = -1; + }else{ +@@ -85376,7 +89315,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( + /* RHS is null */ + else{ + serial_type = aKey1[idx1]; +- rc = (serial_type!=0); ++ rc = (serial_type!=0 && serial_type!=10); + } + + if( rc!=0 ){ +@@ -85398,8 +89337,13 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( + if( i==pPKey2->nField ) break; + pRhs++; + d1 += sqlite3VdbeSerialTypeLen(serial_type); ++ if( d1>(unsigned)nKey1 ) break; + idx1 += sqlite3VarintLen(serial_type); +- }while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 ); ++ 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 +@@ -85800,7 +89744,7 @@ SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){ + */ + SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){ + Vdbe *p; +- for(p = db->pVdbe; p; p=p->pNext){ ++ for(p = db->pVdbe; p; p=p->pVNext){ + p->expired = iCode+1; + } + } +@@ -85893,6 +89837,20 @@ SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){ + 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 +@@ -85921,13 +89879,14 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ + ** 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; i aMem[i]; + if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem); + } +- sqlite3DbFreeNN(db, p); ++ sqlite3DbNNFreeNN(db, p); + } + } + #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +@@ -85954,6 +89913,16 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( + 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)); +@@ -85970,8 +89939,8 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( + + assert( pCsr!=0 ); + assert( pCsr->eCurType==CURTYPE_BTREE ); +- assert( pCsr->nField==pTab->nCol +- || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) ++ assert( pCsr->nField==nRealCol ++ || (pCsr->nField==nRealCol+1 && op==SQLITE_DELETE && iReg==-1) + ); + + preupdate.v = v; +@@ -85998,7 +89967,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( + for(i=0; i nField; i++){ + sqlite3VdbeMemRelease(&preupdate.aNew[i]); + } +- sqlite3DbFreeNN(db, preupdate.aNew); ++ sqlite3DbNNFreeNN(db, preupdate.aNew); + } + } + #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +@@ -86022,6 +89991,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( + */ + /* #include "sqliteInt.h" */ + /* #include "vdbeInt.h" */ ++/* #include "opcodes.h" */ + + #ifndef SQLITE_OMIT_DEPRECATED + /* +@@ -86115,7 +90085,9 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ + if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT; + sqlite3_mutex_enter(db->mutex); + checkProfileCallback(db, v); +- rc = sqlite3VdbeFinalize(v); ++ assert( v->eVdbeState>=VDBE_READY_STATE ); ++ rc = sqlite3VdbeReset(v); ++ sqlite3VdbeDelete(v); + rc = sqlite3ApiExit(db, rc); + sqlite3LeaveMutexAndCloseZombie(db); + } +@@ -86156,7 +90128,15 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int rc = SQLITE_OK; + Vdbe *p = (Vdbe*)pStmt; + #if SQLITE_THREADSAFE +- sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; ++ 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; i nVar; i++){ +@@ -86275,7 +90255,7 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ + SQLITE_NULL, /* 0x1f (not possible) */ + SQLITE_FLOAT, /* 0x20 INTREAL */ + SQLITE_NULL, /* 0x21 (not possible) */ +- SQLITE_TEXT, /* 0x22 INTREAL + TEXT */ ++ SQLITE_FLOAT, /* 0x22 INTREAL + TEXT */ + SQLITE_NULL, /* 0x23 (not possible) */ + SQLITE_FLOAT, /* 0x24 (not possible) */ + SQLITE_NULL, /* 0x25 (not possible) */ +@@ -86323,6 +90303,9 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){ + #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){ +@@ -86376,7 +90359,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value *pOld){ + ** is too big or if an OOM occurs. + ** + ** The invokeValueDestructor(P,X) routine invokes destructor function X() +-** on value P is not going to be used and need to be destroyed. ++** on value P if P is not going to be used and need to be destroyed. + */ + static void setResultStrOrError( + sqlite3_context *pCtx, /* Function context */ +@@ -86406,7 +90389,7 @@ static void setResultStrOrError( + static int invokeValueDestructor( + const void *p, /* Value to destroy */ + void (*xDel)(void*), /* The destructor */ +- sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */ ++ sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if not NULL */ + ){ + assert( xDel!=SQLITE_DYNAMIC ); + if( xDel==0 ){ +@@ -86416,7 +90399,14 @@ static int invokeValueDestructor( + }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( +@@ -86425,6 +90415,12 @@ SQLITE_API void sqlite3_result_blob( + 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); +@@ -86435,8 +90431,14 @@ SQLITE_API void sqlite3_result_blob64( + sqlite3_uint64 n, + void (*xDel)(void *) + ){ +- assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); + 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{ +@@ -86444,30 +90446,48 @@ SQLITE_API void sqlite3_result_blob64( + } + } + 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); + } +@@ -86477,14 +90497,37 @@ SQLITE_API void sqlite3_result_pointer( + const char *zPType, + void (*xDestructor)(void*) + ){ +- Mem *pOut = pCtx->pOut; ++ 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 = pCtx->pOut; ++ 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; +@@ -86495,6 +90538,12 @@ SQLITE_API void sqlite3_result_text( + 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); + } +@@ -86505,13 +90554,23 @@ SQLITE_API void sqlite3_result_text64( + 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_UTF16 ) enc = SQLITE_UTF16NATIVE; ++ 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 +@@ -86522,7 +90581,7 @@ SQLITE_API void sqlite3_result_text16( + void (*xDel)(void *) + ){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +- setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel); ++ setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16NATIVE, xDel); + } + SQLITE_API void sqlite3_result_text16be( + sqlite3_context *pCtx, +@@ -86531,7 +90590,7 @@ SQLITE_API void sqlite3_result_text16be( + void (*xDel)(void *) + ){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +- setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel); ++ setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16BE, xDel); + } + SQLITE_API void sqlite3_result_text16le( + sqlite3_context *pCtx, +@@ -86540,11 +90599,20 @@ SQLITE_API void sqlite3_result_text16le( + void (*xDel)(void *) + ){ + assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +- setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel); ++ 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 = pCtx->pOut; ++ 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); +@@ -86556,7 +90624,12 @@ 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 = pCtx->pOut; ++ 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); +@@ -86570,6 +90643,9 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 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; +@@ -86582,6 +90658,9 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ + + /* 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, +@@ -86590,6 +90669,9 @@ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ + + /* 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; +@@ -86751,7 +90833,7 @@ static int sqlite3Step(Vdbe *p){ + /* 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); +@@ -86842,6 +90924,9 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ + ** 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; + } +@@ -86857,7 +90942,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ + ** 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; + } + +@@ -86876,10 +90965,25 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ + ** 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). +@@ -86893,9 +90997,16 @@ static int valueFromValueList( + ValueList *pRhs; + + *ppOut = 0; +- if( pVal==0 ) return SQLITE_MISUSE; +- pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList"); +- if( pRhs==0 ) return SQLITE_MISUSE; ++ 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{ +@@ -87017,6 +91128,9 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ + 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; +@@ -87049,8 +91163,12 @@ SQLITE_API void sqlite3_set_auxdata( + void (*xDelete)(void*) + ){ + AuxData *pAuxData; +- Vdbe *pVdbe = pCtx->pVdbe; ++ 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; +@@ -87106,7 +91224,8 @@ SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){ + */ + SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; +- return pVm ? pVm->nResColumn : 0; ++ if( pVm==0 ) return 0; ++ return pVm->nResColumn; + } + + /* +@@ -87115,7 +91234,7 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){ + */ + SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; +- if( pVm==0 || pVm->pResultSet==0 ) return 0; ++ if( pVm==0 || pVm->pResultRow==0 ) return 0; + return pVm->nResColumn; + } + +@@ -87170,8 +91289,8 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ + if( pVm==0 ) return (Mem*)columnNullValue(); + assert( pVm->db ); + sqlite3_mutex_enter(pVm->db->mutex); +- if( pVm->pResultSet!=0 && i nResColumn && i>=0 ){ +- pOut = &pVm->pResultSet[i]; ++ if( pVm->pResultRow!=0 && i nResColumn && i>=0 ){ ++ pOut = &pVm->pResultRow[i]; + }else{ + sqlite3Error(pVm->db, SQLITE_RANGE); + pOut = (Mem*)columnNullValue(); +@@ -87195,7 +91314,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ + ** sqlite3_column_real() + ** sqlite3_column_bytes() + ** sqlite3_column_bytes16() +-** sqiite3_column_blob() ++** sqlite3_column_blob() + */ + static void columnMallocFailure(sqlite3_stmt *pStmt) + { +@@ -87279,6 +91398,32 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ + 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. +@@ -87311,15 +91456,29 @@ static const void *columnName( + return 0; + } + #endif ++ if( N<0 ) return 0; + ret = 0; + p = (Vdbe *)pStmt; + db = p->db; + assert( db!=0 ); +- n = sqlite3_column_count(pStmt); +- if( N =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( N mallocFailed; + N += useType*n; +- sqlite3_mutex_enter(db->mutex); +- assert( db->mallocFailed==0 ); + #ifndef SQLITE_OMIT_UTF16 + if( useUtf16 ){ + ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); +@@ -87331,12 +91490,14 @@ static const void *columnName( + /* A malloc may have failed inside of the _text() call. If this + ** is the case, clear the mallocFailed flag and return NULL. + */ +- if( db->mallocFailed ){ ++ assert( db->mallocFailed==0 || db->mallocFailed==1 ); ++ if( db->mallocFailed > prior_mallocFailed ){ + sqlite3OomClear(db); + ret = 0; + } +- sqlite3_mutex_leave(db->mutex); + } ++columnName_end: ++ sqlite3_mutex_leave(db->mutex); + return ret; + } + +@@ -87429,7 +91590,7 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ + /* + ** 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. Othewise SQLITE_OK. ++** 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. +@@ -87437,25 +91598,24 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ + ** The error code stored in database p->db is overwritten with the return + ** value in any case. + */ +-static int vdbeUnbind(Vdbe *p, int i){ ++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); ++ 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<1 || i>p->nVar ){ ++ if( i>=(unsigned int)p->nVar ){ + sqlite3Error(p->db, SQLITE_RANGE); + sqlite3_mutex_leave(p->db->mutex); + return SQLITE_RANGE; + } +- i--; + pVar = &p->aVar[i]; + sqlite3VdbeMemRelease(pVar); + pVar->flags = MEM_Null; +@@ -87492,7 +91652,7 @@ static int bindText( + Mem *pVar; + int rc; + +- rc = vdbeUnbind(p, i); ++ rc = vdbeUnbind(p, (u32)(i-1)); + if( rc==SQLITE_OK ){ + if( zData!=0 ){ + pVar = &p->aVar[i-1]; +@@ -87541,7 +91701,7 @@ SQLITE_API int sqlite3_bind_blob64( + SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; +- rc = vdbeUnbind(p, i); ++ rc = vdbeUnbind(p, (u32)(i-1)); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); + sqlite3_mutex_leave(p->db->mutex); +@@ -87554,7 +91714,7 @@ SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ + SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; +- rc = vdbeUnbind(p, i); ++ rc = vdbeUnbind(p, (u32)(i-1)); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); + sqlite3_mutex_leave(p->db->mutex); +@@ -87564,7 +91724,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu + SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ + int rc; + Vdbe *p = (Vdbe*)pStmt; +- rc = vdbeUnbind(p, i); ++ rc = vdbeUnbind(p, (u32)(i-1)); + if( rc==SQLITE_OK ){ + sqlite3_mutex_leave(p->db->mutex); + } +@@ -87579,7 +91739,7 @@ SQLITE_API int sqlite3_bind_pointer( + ){ + int rc; + Vdbe *p = (Vdbe*)pStmt; +- rc = vdbeUnbind(p, i); ++ rc = vdbeUnbind(p, (u32)(i-1)); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor); + sqlite3_mutex_leave(p->db->mutex); +@@ -87606,7 +91766,10 @@ SQLITE_API int sqlite3_bind_text64( + unsigned char enc + ){ + assert( xDel!=SQLITE_DYNAMIC ); +- if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; ++ if( enc!=SQLITE_UTF8 ){ ++ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; ++ nData &= ~(u16)1; ++ } + return bindText(pStmt, i, zData, nData, xDel, enc); + } + #ifndef SQLITE_OMIT_UTF16 +@@ -87614,10 +91777,10 @@ SQLITE_API int sqlite3_bind_text16( + sqlite3_stmt *pStmt, + int i, + const void *zData, +- int nData, ++ int n, + void (*xDel)(void*) + ){ +- return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE); ++ 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){ +@@ -87657,7 +91820,7 @@ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_valu + SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ + int rc; + Vdbe *p = (Vdbe *)pStmt; +- rc = vdbeUnbind(p, i); ++ rc = vdbeUnbind(p, (u32)(i-1)); + if( rc==SQLITE_OK ){ + #ifndef SQLITE_OMIT_INCRBLOB + sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); +@@ -87671,6 +91834,9 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ + 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; +@@ -87791,6 +91957,42 @@ 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. + */ +@@ -87817,7 +92019,7 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ + if( pStmt==0 ){ + pNext = (sqlite3_stmt*)pDb->pVdbe; + }else{ +- pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext; ++ pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pVNext; + } + sqlite3_mutex_leave(pDb->mutex); + return pNext; +@@ -87842,8 +92044,11 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ + 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]; +@@ -87927,10 +92132,16 @@ static UnpackedRecord *vdbeUnpackRecord( + ** 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 = db->pPreUpdate; ++ PreUpdate *p; + Mem *pMem; + int rc = SQLITE_OK; + ++#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 ){ +@@ -87991,7 +92202,12 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa + ** the number of columns in the row being updated, deleted or inserted. + */ + SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ +- PreUpdate *p = db->pPreUpdate; ++ PreUpdate *p; ++#ifdef SQLITE_ENABLE_API_ARMOR ++ p = db!=0 ? db->pPreUpdate : 0; ++#else ++ p = db->pPreUpdate; ++#endif + return (p ? p->keyinfo.nKeyField : 0); + } + #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ +@@ -88009,7 +92225,12 @@ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ + ** or SET DEFAULT action is considered a trigger. + */ + SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ +- PreUpdate *p = db->pPreUpdate; ++ 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 */ +@@ -88020,7 +92241,12 @@ SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){ + ** only. + */ + SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ +- PreUpdate *p = db->pPreUpdate; ++ PreUpdate *p; ++#ifdef SQLITE_ENABLE_API_ARMOR ++ p = db!=0 ? db->pPreUpdate : 0; ++#else ++ p = db->pPreUpdate; ++#endif + return (p ? p->iBlobWrite : -1); + } + #endif +@@ -88031,10 +92257,16 @@ SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){ + ** 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 = db->pPreUpdate; ++ PreUpdate *p; + int rc = SQLITE_OK; + Mem *pMem; + ++#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; +@@ -88105,23 +92337,78 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa + /* + ** Return status data for a single loop within query pStmt. + */ +-SQLITE_API int sqlite3_stmt_scanstatus( ++SQLITE_API int sqlite3_stmt_scanstatus_v2( + sqlite3_stmt *pStmt, /* Prepared statement being queried */ +- int idx, /* Index of loop to report on */ ++ 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; +- ScanStatus *pScan; +- if( idx<0 || idx>=p->nScan ) return 1; +- pScan = &p->aScan[idx]; ++ VdbeOp *aOp; ++ int nOp; ++ ScanStatus *pScan = 0; ++ int idx; ++ ++#ifdef SQLITE_ENABLE_API_ARMOR ++ if( p==0 || pOut==0 ++ || iScanStatusOp SQLITE_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; ii aScan[idx]; ++ }else{ ++ /* If the COMPLEX flag is clear, then this function must ignore any ++ ** ScanStatus structures with ScanStatus.addrLoop set to 0. */ ++ for(idx=0; idx nScan; idx++){ ++ pScan = &p->aScan[idx]; ++ if( pScan->zName ){ ++ iScan--; ++ if( iScan<0 ) break; ++ } ++ } ++ } ++ if( idx>=p->nScan ) return 1; ++ + switch( iScanStatusOp ){ + case SQLITE_SCANSTAT_NLOOP: { +- *(sqlite3_int64*)pOut = p->anExec[pScan->addrLoop]; ++ if( pScan->addrLoop>0 ){ ++ *(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec; ++ }else{ ++ *(sqlite3_int64*)pOut = -1; ++ } + break; + } + case SQLITE_SCANSTAT_NVISIT: { +- *(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit]; ++ if( pScan->addrVisit>0 ){ ++ *(sqlite3_int64*)pOut = aOp[pScan->addrVisit].nExec; ++ }else{ ++ *(sqlite3_int64*)pOut = -1; ++ } + break; + } + case SQLITE_SCANSTAT_EST: { +@@ -88140,7 +92427,7 @@ SQLITE_API int sqlite3_stmt_scanstatus( + } + case SQLITE_SCANSTAT_EXPLAIN: { + if( pScan->addrExplain ){ +- *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; ++ *(const char**)pOut = aOp[ pScan->addrExplain ].p4.z; + }else{ + *(const char**)pOut = 0; + } +@@ -88148,12 +92435,51 @@ SQLITE_API int sqlite3_stmt_scanstatus( + } + case SQLITE_SCANSTAT_SELECTID: { + if( pScan->addrExplain ){ +- *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; ++ *(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; ii aAddrRange); 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; iOp p1!=iEnd ) continue; ++ if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){ ++ continue; ++ } ++ res += aOp[iOp].nCycle; ++ } ++ } ++ } ++ } ++ *(i64*)pOut = res; ++ break; ++ } + default: { + return 1; + } +@@ -88161,12 +92487,29 @@ SQLITE_API int sqlite3_stmt_scanstatus( + 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; +- memset(p->anExec, 0, p->nOp * sizeof(i64)); ++ int ii; ++ for(ii=0; p!=0 && ii nOp; ii++){ ++ Op *pOp = &p->aOp[ii]; ++ pOp->nExec = 0; ++ pOp->nCycle = 0; ++ } + } + #endif /* SQLITE_ENABLE_STMT_SCANSTATUS */ + +@@ -88501,8 +92844,12 @@ SQLITE_API int sqlite3_found_count = 0; + ** sqlite3CantopenError(lineno) + */ + static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){ +- static int n = 0; ++ 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 + +@@ -88683,7 +93030,8 @@ static VdbeCursor *allocateCursor( + ** return false. + */ + static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){ +- i64 iValue = (double)rValue; ++ i64 iValue; ++ iValue = sqlite3RealToI64(rValue); + if( sqlite3RealSameAsInt(rValue,iValue) ){ + *piValue = iValue; + return 1; +@@ -88739,6 +93087,10 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ + ** 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. + ** +@@ -88753,11 +93105,11 @@ static void applyAffinity( + ){ + if( affinity>=SQLITE_AFF_NUMERIC ){ + assert( affinity==SQLITE_AFF_INTEGER || affinity==SQLITE_AFF_REAL +- || affinity==SQLITE_AFF_NUMERIC ); ++ || affinity==SQLITE_AFF_NUMERIC || affinity==SQLITE_AFF_FLEXNUM ); + if( (pRec->flags & MEM_Int)==0 ){ /*OPTIMIZATION-IF-FALSE*/ +- if( (pRec->flags & MEM_Real)==0 ){ ++ if( (pRec->flags & (MEM_Real|MEM_IntReal))==0 ){ + if( pRec->flags & MEM_Str ) applyNumericAffinity(pRec,1); +- }else{ ++ }else if( affinity<=SQLITE_AFF_REAL ){ + sqlite3VdbeIntegerAffinity(pRec); + } + } +@@ -88845,17 +93197,18 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ + ** But it does set pMem->u.r and pMem->u.i appropriately. + */ + static u16 numericType(Mem *pMem){ +- if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal) ){ ++ 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); +- } +- if( pMem->flags & (MEM_Str|MEM_Blob) ){ +- testcase( pMem->flags & MEM_Str ); +- testcase( pMem->flags & MEM_Blob ); +- return computeNumericType(pMem); ++ 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; + } + +@@ -88916,6 +93269,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){ + 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 +@@ -88984,17 +93340,6 @@ SQLITE_PRIVATE void sqlite3VdbeRegisterDump(Vdbe *v){ + # define REGISTER_TRACE(R,M) + #endif + +- +-#ifdef VDBE_PROFILE +- +-/* +-** hwtime.h contains inline assembler code for implementing +-** high-performance timing routines. +-*/ +-/* #include "hwtime.h" */ +- +-#endif +- + #ifndef NDEBUG + /* + ** This function is only called from within an assert() expression. It +@@ -89054,13 +93399,102 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){ + }else if( p->flags & MEM_Real ){ + h += sqlite3VdbeIntValue(p); + }else if( p->flags & (MEM_Str|MEM_Blob) ){ +- h += p->n; +- if( p->flags & MEM_Zero ) h += p->u.nZero; ++ /* 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 + */ +@@ -89084,11 +93518,10 @@ SQLITE_PRIVATE int sqlite3VdbeExec( + ){ + Op *aOp = p->aOp; /* Copy of p->aOp */ + Op *pOp = aOp; /* Current operation */ +-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +- Op *pOrigOp; /* Value of pOp at the top of the loop */ +-#endif + #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 */ +@@ -89104,13 +93537,17 @@ SQLITE_PRIVATE int sqlite3VdbeExec( + Mem *pIn2 = 0; /* 2nd input operand */ + Mem *pIn3 = 0; /* 3rd input operand */ + Mem *pOut = 0; /* Output operand */ +-#ifdef VDBE_PROFILE +- u64 start; /* CPU clock count at start of opcode */ ++ 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 */ +- sqlite3VdbeEnter(p); ++ if( DbMaskNonZero(p->lockMask) ){ ++ sqlite3VdbeEnter(p); ++ } + #ifndef SQLITE_OMIT_PROGRESS_CALLBACK + if( db->xProgress ){ + u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; +@@ -89131,7 +93568,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec( + assert( p->bIsReader || p->readOnly!=0 ); + p->iCurrentTime = 0; + assert( p->explain==0 ); +- p->pResultSet = 0; + db->busyHandler.nBusy = 0; + if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt; + sqlite3VdbeIOTraceSql(p); +@@ -89168,12 +93604,18 @@ SQLITE_PRIVATE int sqlite3VdbeExec( + assert( rc==SQLITE_OK ); + + assert( pOp>=aOp && pOp<&aOp[p->nOp]); +-#ifdef VDBE_PROFILE +- start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); +-#endif + nVmStep++; +-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- if( p->anExec ) p->anExec[(int)(pOp-aOp)]++; ++ ++#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. +@@ -89235,7 +93677,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( + } + } + #endif +-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) ++#ifdef SQLITE_DEBUG + pOrigOp = pOp; + #endif + +@@ -89291,8 +93733,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec( + case OP_Goto: { /* jump */ + + #ifdef SQLITE_DEBUG +- /* In debuggging mode, when the p5 flags is set on an OP_Goto, that +- ** means we should really jump back to the preceeding OP_ReleaseReg ++ /* 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) ); +@@ -89500,7 +93942,7 @@ case OP_HaltIfNull: { /* in3 */ + ** P5 is a value between 0 and 4, inclusive, that modifies the P4 string. + ** + ** 0: (no change) +-** 1: NOT NULL contraint failed: P4 ++** 1: NOT NULL constraint failed: P4 + ** 2: UNIQUE constraint failed: P4 + ** 3: CHECK constraint failed: P4 + ** 4: FOREIGN KEY constraint failed: P4 +@@ -89519,6 +93961,12 @@ case OP_Halt: { + #ifdef SQLITE_DEBUG + if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } + #endif ++ ++ /* 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; +@@ -89960,10 +94408,10 @@ case OP_ResultRow: { + assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); + + p->cacheCtr = (p->cacheCtr + 2)|1; +- p->pResultSet = &aMem[pOp->p1]; ++ p->pResultRow = &aMem[pOp->p1]; + #ifdef SQLITE_DEBUG + { +- Mem *pMem = p->pResultSet; ++ Mem *pMem = p->pResultRow; + int i; + for(i=0; i p2; i++){ + assert( memIsValid(&pMem[i]) ); +@@ -90100,7 +94548,6 @@ 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 flags; /* Combined MEM_* flags from both inputs */ + u16 type1; /* Numeric type of left operand */ + u16 type2; /* Numeric type of right operand */ + i64 iA; /* Integer value of left operand */ +@@ -90109,12 +94556,12 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ + double rB; /* Real value of right operand */ + + pIn1 = &aMem[pOp->p1]; +- type1 = numericType(pIn1); ++ type1 = pIn1->flags; + pIn2 = &aMem[pOp->p2]; +- type2 = numericType(pIn2); ++ type2 = pIn2->flags; + pOut = &aMem[pOp->p3]; +- flags = pIn1->flags | pIn2->flags; + if( (type1 & type2 & MEM_Int)!=0 ){ ++int_math: + iA = pIn1->u.i; + iB = pIn2->u.i; + switch( pOp->opcode ){ +@@ -90136,9 +94583,12 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ + } + pOut->u.i = iB; + MemSetTypeFlag(pOut, MEM_Int); +- }else if( (flags & MEM_Null)!=0 ){ ++ }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); +@@ -90296,7 +94746,7 @@ case OP_AddImm: { /* in1 */ + pIn1 = &aMem[pOp->p1]; + memAboutToChange(p, pIn1); + sqlite3VdbeMemIntegerify(pIn1); +- pIn1->u.i += pOp->p2; ++ *(u64*)&pIn1->u.i += (u64)pOp->p2; + break; + } + +@@ -90491,7 +94941,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + flags1 = pIn1->flags; + flags3 = pIn3->flags; + if( (flags1 & flags3 & MEM_Int)!=0 ){ +- assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB ); + /* Common case of comparison of two integers */ + if( pIn3->u.i > pIn1->u.i ){ + if( sqlite3aGTb[pOp->opcode] ){ +@@ -90499,18 +94948,21 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + 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; +@@ -90542,6 +94994,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + goto jump_to_p2; + } + iCompare = 1; /* Operands are not equal */ ++ VVA_ONLY( iCompareIsInit = 1; ) + break; + } + }else{ +@@ -90552,14 +95005,14 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + if( (flags1 | flags3)&MEM_Str ){ + if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){ + applyNumericAffinity(pIn1,0); +- testcase( flags3==pIn3->flags ); ++ 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 ){ ++ }else if( affinity==SQLITE_AFF_TEXT && ((flags1 | flags3) & MEM_Str)!=0 ){ + if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ + testcase( pIn1->flags & MEM_Int ); + testcase( pIn1->flags & MEM_Real ); +@@ -90567,7 +95020,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + sqlite3VdbeMemStringify(pIn1, encoding, 1); + testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); + flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); +- if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str; ++ if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str; + } + if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ + testcase( pIn3->flags & MEM_Int ); +@@ -90598,6 +95051,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + 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) ); +@@ -90619,10 +95073,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ + ** opcodes are allowed to occur between this instruction and the previous + ** OP_Lt or OP_Gt. + ** +-** If result of an OP_Eq comparison on the same two operands as the +-** prior OP_Lt or OP_Gt would have been 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. ++** 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 */ + +@@ -90636,6 +95090,7 @@ case OP_ElseEq: { /* same as TK_ESCAPE, jump */ + break; + } + #endif /* SQLITE_DEBUG */ ++ assert( iCompareIsInit ); + VdbeBranchTaken(iCompare==0, 2); + if( iCompare==0 ) goto jump_to_p2; + break; +@@ -90730,6 +95185,7 @@ case OP_Compare: { + 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)) +@@ -90747,13 +95203,14 @@ case OP_Compare: { + /* 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 ++** 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 ){ +@@ -90953,26 +95410,103 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ + break; + } + +-/* Opcode: IsNullOrType P1 P2 P3 * * +-** Synopsis: if typeof(r[P1]) IN (P3,5) goto P2 ++/* 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. + ** +-** Jump to P2 if the value in register P1 is NULL or has a datatype P3. +-** P3 is an integer which should be one of SQLITE_INTEGER, SQLITE_FLOAT, +-** SQLITE_BLOB, SQLITE_NULL, or SQLITE_TEXT. + */ +-case OP_IsNullOrType: { /* jump, in1 */ +- int doTheJump; +- pIn1 = &aMem[pOp->p1]; +- doTheJump = (pIn1->flags & MEM_Null)!=0 || sqlite3_value_type(pIn1)==pOp->p3; +- VdbeBranchTaken( doTheJump, 2); +- if( doTheJump ) goto jump_to_p2; ++case OP_IsType: { /* jump */ ++ VdbeCursor *pC; ++ u16 typeMask; ++ u32 serialType; ++ ++ assert( pOp->p1>=(-1) && pOp->p1 nCursor ); ++ 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->p3 nHdrParsed ){ ++ 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 all both registers P1 and P3 are NOT NULL, then store a zero in ++** 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. + */ +@@ -91008,11 +95542,14 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ + ** 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->p1 nCursor ); +- assert( p->apCsr[pOp->p1]!=0 ); +- if( p->apCsr[pOp->p1]->nullRow ){ ++ pC = p->apCsr[pOp->p1]; ++ if( pC && pC->nullRow ){ + sqlite3VdbeMemSetNull(aMem + pOp->p3); + goto jump_to_p2; + } +@@ -91063,7 +95600,7 @@ case OP_Offset: { /* out3 */ + ** 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 that (P2+1) ++** 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. +@@ -91072,12 +95609,14 @@ case OP_Offset: { /* out3 */ + ** if the P4 argument is a P4_MEM use the value of the P4 argument as + ** the result. + ** +-** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then +-** the result is guaranteed to only be used as the argument of a length() +-** or typeof() function, respectively. The loading of large blobs can be +-** skipped for length() and all content loading can be skipped for typeof(). ++** 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: { ++case OP_Column: { /* ncycle */ + u32 p2; /* column number to retrieve */ + VdbeCursor *pC; /* The VDBE cursor */ + BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */ +@@ -91321,11 +95860,16 @@ op_column_restart: + 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( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 +- && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)) +- || (len = sqlite3VdbeSerialTypeLen(t))==0 ++ 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, +@@ -91342,11 +95886,13 @@ op_column_restart: + */ + sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); + }else{ +- if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big; +- rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest); +- if( rc!=SQLITE_OK ) goto abort_due_to_error; +- sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); +- pDest->flags &= ~MEM_Ephem; ++ 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; ++ } + } + } + +@@ -91426,7 +95972,7 @@ case OP_TypeCheck: { + } + case COLTYPE_REAL: { + testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real ); +- testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_IntReal ); ++ 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 +@@ -91505,7 +96051,7 @@ case OP_Affinity: { + }else{ + pIn1->u.r = (double)pIn1->u.i; + pIn1->flags |= MEM_Real; +- pIn1->flags &= ~MEM_Int; ++ pIn1->flags &= ~(MEM_Int|MEM_Str); + } + } + REGISTER_TRACE((int)(pIn1-aMem), pIn1); +@@ -91808,7 +96354,6 @@ case OP_MakeRecord: { + /* NULL value. No change in zPayload */ + }else{ + u64 v; +- u32 i; + if( serial_type==7 ){ + assert( sizeof(v)==sizeof(pRec->u.r) ); + memcpy(&v, &pRec->u.r, sizeof(v)); +@@ -91816,12 +96361,17 @@ case OP_MakeRecord: { + }else{ + v = pRec->u.i; + } +- len = i = sqlite3SmallTypeSizes[serial_type]; +- assert( i>0 ); +- while( 1 /*exit-by-break*/ ){ +- zPayload[--i] = (u8)(v&0xFF); +- if( i==0 ) break; +- v >>= 8; ++ 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; ++ case 6: zPayload[5] = (u8)(v&0xff); v >>= 8; ++ zPayload[4] = (u8)(v&0xff); v >>= 8; ++ case 4: zPayload[3] = (u8)(v&0xff); v >>= 8; ++ case 3: zPayload[2] = (u8)(v&0xff); v >>= 8; ++ case 2: zPayload[1] = (u8)(v&0xff); v >>= 8; ++ case 1: zPayload[0] = (u8)(v&0xff); + } + zPayload += len; + } +@@ -92429,7 +96979,7 @@ case OP_SetCookie: { + ** + ** See also: OP_OpenRead, OP_ReopenIdx + */ +-case OP_ReopenIdx: { ++case OP_ReopenIdx: { /* ncycle */ + int nField; + KeyInfo *pKeyInfo; + u32 p2; +@@ -92450,7 +97000,7 @@ case OP_ReopenIdx: { + } + /* If the cursor is not currently open or is open on a different + ** index, then fall through into OP_OpenRead to force a reopen */ +-case OP_OpenRead: ++case OP_OpenRead: /* ncycle */ + case OP_OpenWrite: + + assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); +@@ -92544,7 +97094,7 @@ open_cursor_set_hints: + ** + ** Duplicate ephemeral cursors are used for self-joins of materialized views. + */ +-case OP_OpenDup: { ++case OP_OpenDup: { /* ncycle */ + VdbeCursor *pOrig; /* The original cursor to be duplicated */ + VdbeCursor *pCx; /* The new cursor */ + +@@ -92606,8 +97156,8 @@ case OP_OpenDup: { + ** by this opcode will be used for automatically created transient + ** indices in joins. + */ +-case OP_OpenAutoindex: +-case OP_OpenEphemeral: { ++case OP_OpenAutoindex: /* ncycle */ ++case OP_OpenEphemeral: { /* ncycle */ + VdbeCursor *pCx; + KeyInfo *pKeyInfo; + +@@ -92630,7 +97180,7 @@ case OP_OpenEphemeral: { + } + pCx = p->apCsr[pOp->p1]; + if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){ +- /* If the ephermeral table is already open and has no duplicates from ++ /* 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 ); +@@ -92765,7 +97315,7 @@ case OP_OpenPseudo: { + ** Close a cursor previously opened as P1. If P1 is not + ** currently open, this instruction is a no-op. + */ +-case OP_Close: { ++case OP_Close: { /* ncycle */ + assert( pOp->p1>=0 && pOp->p1 nCursor ); + sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]); + p->apCsr[pOp->p1] = 0; +@@ -92882,10 +97432,10 @@ case OP_ColumnsUsed: { + ** + ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt + */ +-case OP_SeekLT: /* jump, in3, group */ +-case OP_SeekLE: /* jump, in3, group */ +-case OP_SeekGE: /* jump, in3, group */ +-case OP_SeekGT: { /* jump, in3, group */ ++case OP_SeekLT: /* jump, in3, group, ncycle */ ++case OP_SeekLE: /* jump, in3, group, ncycle */ ++case OP_SeekGE: /* jump, in3, group, ncycle */ ++case OP_SeekGT: { /* jump, in3, group, ncycle */ + int res; /* Comparison result */ + int oc; /* Opcode */ + VdbeCursor *pC; /* The cursor to seek */ +@@ -93014,7 +97564,13 @@ case OP_SeekGT: { /* jump, in3, group */ + + r.aMem = &aMem[pOp->p3]; + #ifdef SQLITE_DEBUG +- { int i; for(i=0; i 0 ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]); ++ } ++ } + #endif + r.eqSeen = 0; + rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res); +@@ -93077,7 +97633,7 @@ seek_not_found: + } + + +-/* Opcode: SeekScan P1 P2 * * * ++/* 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 +@@ -93087,8 +97643,8 @@ seek_not_found: + ** 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 and P2 operands of this opcode are also used, and are called +-** This.P1 and This.P2. ++** 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 +@@ -93098,32 +97654,54 @@ seek_not_found: + ** + ** 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.P4/P5 row the "target". ++** 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. This opcode attempts to position the cursor on the target +-** row by, perhaps by invoking sqlite3BtreeStep() on the cursor +-** between 0 and This.P1 times. +-** +-** There are three possible outcomes from this opcode: +-** +-**
- If after This.P1 steps, the cursor is still pointing to a place that +-** is earlier in the btree than the target row, then fall through +-** into the subsquence OP_SeekGE opcode. +-** +-**
- If the cursor is successfully moved to the target row by 0 or more +-** sqlite3BtreeNext() calls, then jump to This.P2, which will land just +-** past the OP_IdxGT or OP_IdxGE opcode that follows the OP_SeekGE. +-** +-**
- If the cursor ends up past the target row (indicating the the target +-** row does not exist in the btree) then jump to SeekOP.P2. ++** 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:
++** ++**
+ */ +-case OP_SeekScan: { ++case OP_SeekScan: { /* ncycle */ + VdbeCursor *pC; + int res; + int nStep; +@@ -93131,14 +97709,25 @@ case OP_SeekScan: { + + assert( pOp[1].opcode==OP_SeekGE ); + +- /* pOp->p2 points to the first instruction past the OP_IdxGT that +- ** follows the 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 ); +- assert( aOp[pOp->p2-1].opcode==OP_IdxGT || aOp[pOp->p2-1].opcode==OP_IdxGE ); +- testcase( aOp[pOp->p2-1].opcode==OP_IdxGE ); +- assert( pOp[1].p1==aOp[pOp->p2-1].p1 ); +- assert( pOp[1].p2==aOp[pOp->p2-1].p2 ); +- assert( pOp[1].p3==aOp[pOp->p2-1].p3 ); ++#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]; +@@ -93172,8 +97761,9 @@ case OP_SeekScan: { + while(1){ + rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res); + if( rc ) goto abort_due_to_error; +- if( res>0 ){ ++ if( res>0 && 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); +@@ -93183,7 +97773,8 @@ case OP_SeekScan: { + pOp++; + goto jump_to_p2; + } +- if( res==0 ){ ++ 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); +@@ -93203,6 +97794,7 @@ case OP_SeekScan: { + break; + } + nStep--; ++ pC->cacheStatus = CACHE_STALE; + rc = sqlite3BtreeNext(pC->uc.pCursor, 0); + if( rc ){ + if( rc==SQLITE_DONE ){ +@@ -93232,7 +97824,7 @@ case OP_SeekScan: { + ** + ** P1 must be a valid b-tree cursor. + */ +-case OP_SeekHit: { ++case OP_SeekHit: { /* ncycle */ + VdbeCursor *pC; + assert( pOp->p1>=0 && pOp->p1- If the cursor is initially not pointed to any valid row, then ++** fall through into the subsequent OP_SeekGE opcode. ++** ++**
- 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. ++** ++**
- 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.., ++** ++**
- 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. ++** ++**
- 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. + **
nCursor ); + pC = p->apCsr[pOp->p1]; +@@ -93259,12 +97851,16 @@ case OP_SeekHit: { + /* Opcode: IfNotOpen P1 P2 * * * + ** Synopsis: if( !csr[P1] ) goto P2 + ** +-** If cursor P1 is not open, jump to instruction P2. Otherwise, fall through. ++** 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->p1 nCursor ); +- VdbeBranchTaken(p->apCsr[pOp->p1]==0, 2); +- if( !p->apCsr[pOp->p1] ){ ++ 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; +@@ -93315,13 +97911,13 @@ case OP_IfNotOpen: { /* jump */ + ** 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 works ++** 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 skips some work. So if seekHit ++** 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. + ** +@@ -93360,7 +97956,7 @@ case OP_IfNotOpen: { /* jump */ + ** + ** See also: NotFound, Found, NotExists + */ +-case OP_IfNoHope: { /* jump, in3 */ ++case OP_IfNoHope: { /* jump, in3, ncycle */ + VdbeCursor *pC; + assert( pOp->p1>=0 && pOp->p1 nCursor ); + pC = p->apCsr[pOp->p1]; +@@ -93374,9 +97970,9 @@ case OP_IfNoHope: { /* jump, in3 */ + /* Fall through into OP_NotFound */ + /* no break */ deliberate_fall_through + } +-case OP_NoConflict: /* jump, in3 */ +-case OP_NotFound: /* jump, in3 */ +-case OP_Found: { /* jump, in3 */ ++case OP_NoConflict: /* jump, in3, ncycle */ ++case OP_NotFound: /* jump, in3, ncycle */ ++case OP_Found: { /* jump, in3, ncycle */ + int alreadyExists; + int ii; + VdbeCursor *pC; +@@ -93506,7 +98102,7 @@ case OP_Found: { /* jump, in3 */ + ** + ** See also: Found, NotFound, NoConflict, SeekRowid + */ +-case OP_SeekRowid: { /* jump, in3 */ ++case OP_SeekRowid: { /* jump, in3, ncycle */ + VdbeCursor *pC; + BtCursor *pCrsr; + int res; +@@ -93531,7 +98127,7 @@ case OP_SeekRowid: { /* jump, in3 */ + } + /* Fall through into OP_NotExists */ + /* no break */ deliberate_fall_through +-case OP_NotExists: /* jump, in3 */ ++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->p1 nCursor ); +@@ -93811,8 +98407,11 @@ case OP_Insert: { + if( pOp->p5 & OPFLAG_ISNOOP ) break; + #endif + +- if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; +- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; ++ 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; +@@ -93823,12 +98422,14 @@ case OP_Insert: { + 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; +@@ -93882,13 +98483,18 @@ case OP_RowCell: { + ** left in an undefined state. + ** + ** If the OPFLAG_AUXDELETE bit is set on P5, that indicates that this +-** delete 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. ++** 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_NCHANGE 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. +@@ -93989,6 +98595,7 @@ case OP_Delete: { + + rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); + pC->cacheStatus = CACHE_STALE; ++ colCacheCtr++; + pC->seekResult = 0; + if( rc ) goto abort_due_to_error; + +@@ -94056,13 +98663,13 @@ case OP_SorterCompare: { + ** 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 use to move a record out of the sorter and into ++** 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: { ++case OP_SorterData: { /* ncycle */ + VdbeCursor *pC; + + pOut = &aMem[pOp->p2]; +@@ -94154,7 +98761,7 @@ case OP_RowData: { + ** 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 */ ++case OP_Rowid: { /* out2, ncycle */ + VdbeCursor *pC; + i64 v; + sqlite3_vtab *pVtab; +@@ -94253,8 +98860,8 @@ case OP_NullRow: { + ** from the end toward the beginning. In other words, the cursor is + ** configured to use Prev, not Next. + */ +-case OP_SeekEnd: +-case OP_Last: { /* jump */ ++case OP_SeekEnd: /* ncycle */ ++case OP_Last: { /* jump, ncycle */ + VdbeCursor *pC; + BtCursor *pCrsr; + int res; +@@ -94337,8 +98944,8 @@ case OP_IfSmaller: { /* jump */ + ** regression tests can determine whether or not the optimizer is + ** correctly optimizing out sorts. + */ +-case OP_SorterSort: /* jump */ +-case OP_Sort: { /* jump */ ++case OP_SorterSort: /* jump ncycle */ ++case OP_Sort: { /* jump ncycle */ + #ifdef SQLITE_TEST + sqlite3_sort_count++; + sqlite3_search_count--; +@@ -94355,17 +98962,22 @@ case OP_Sort: { /* jump */ + ** 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: { /* jump */ ++case OP_Rewind: { /* jump, ncycle */ + VdbeCursor *pC; + BtCursor *pCrsr; + int res; + + assert( pOp->p1>=0 && pOp->p1 nCursor ); + assert( pOp->p5==0 ); ++ assert( pOp->p2>=0 && pOp->p2 nOp ); ++ + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); +@@ -94385,9 +98997,10 @@ case OP_Rewind: { /* jump */ + } + if( rc ) goto abort_due_to_error; + pC->nullRow = (u8)res; +- assert( pOp->p2>0 && pOp->p2 nOp ); +- VdbeBranchTaken(res!=0,2); +- if( res ) goto jump_to_p2; ++ if( pOp->p2>0 ){ ++ VdbeBranchTaken(res!=0,2); ++ if( res ) goto jump_to_p2; ++ } + break; + } + +@@ -94453,9 +99066,11 @@ case OP_SorterNext: { /* jump */ + rc = sqlite3VdbeSorterNext(db, pC); + goto next_tail; + +-case OP_Prev: /* jump */ ++case OP_Prev: /* jump, ncycle */ + assert( pOp->p1>=0 && pOp->p1 nCursor ); +- assert( pOp->p5 aCounter) ); ++ 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 ); +@@ -94466,9 +99081,11 @@ case OP_Prev: /* jump */ + rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3); + goto next_tail; + +-case OP_Next: /* jump */ ++case OP_Next: /* jump, ncycle */ + assert( pOp->p1>=0 && pOp->p1 nCursor ); +- assert( pOp->p5 aCounter) ); ++ 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 ); +@@ -94656,8 +99273,8 @@ case OP_IdxDelete: { + ** + ** See also: Rowid, MakeRecord. + */ +-case OP_DeferredSeek: +-case OP_IdxRowid: { /* out2 */ ++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 */ +@@ -94675,10 +99292,10 @@ case OP_IdxRowid: { /* out2 */ + ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */ + rc = sqlite3VdbeCursorRestore(pC); + +- /* sqlite3VbeCursorRestore() can only fail if the record has been deleted +- ** out from under the cursor. That will never happens for an IdxRowid +- ** or Seek opcode */ +- if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error; ++ /* 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. */ +@@ -94719,8 +99336,8 @@ case OP_IdxRowid: { /* out2 */ + ** seek operation now, without further delay. If the cursor seek has + ** already occurred, this instruction is a no-op. + */ +-case OP_FinishSeek: { +- VdbeCursor *pC; /* The P1 index cursor */ ++case OP_FinishSeek: { /* ncycle */ ++ VdbeCursor *pC; /* The P1 index cursor */ + + assert( pOp->p1>=0 && pOp->p1 nCursor ); + pC = p->apCsr[pOp->p1]; +@@ -94775,10 +99392,10 @@ case OP_FinishSeek: { + ** If the P1 index entry is less than or equal to the key value then jump + ** to P2. Otherwise fall through to the next instruction. + */ +-case OP_IdxLE: /* jump */ +-case OP_IdxGT: /* jump */ +-case OP_IdxLT: /* jump */ +-case OP_IdxGE: { /* jump */ ++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; +@@ -94855,7 +99472,7 @@ case OP_IdxGE: { /* jump */ + ** 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 clear is in the auxiliary database file ++** 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 +@@ -94915,8 +99532,8 @@ case OP_Destroy: { /* out2 */ + ** 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 clear is in the main database file if P2==0. If +-** P2==1 then the table to be clear is in the auxiliary 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 +@@ -95002,13 +99619,41 @@ case OP_CreateBtree: { /* out2 */ + /* Opcode: SqlExec * * * P4 * + ** + ** Run the SQL statement or statements specified in the P4 string. ++** Disable Auth and Trace callbacks while those statements are running if ++** P1 is true. + */ + case OP_SqlExec: { ++ char *zErr; ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ sqlite3_xauth xAuth; ++#endif ++ u8 mTrace; ++ + sqlite3VdbeIncrWriteCounter(p, 0); + db->nSqlExec++; +- rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); ++ zErr = 0; ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ xAuth = db->xAuth; ++#endif ++ mTrace = db->mTrace; ++ if( pOp->p1 ){ ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = 0; ++#endif ++ db->mTrace = 0; ++ } ++ rc = sqlite3_exec(db, pOp->p4.z, 0, 0, &zErr); + db->nSqlExec--; +- if( rc ) goto abort_due_to_error; ++#ifndef SQLITE_OMIT_AUTHORIZATION ++ db->xAuth = xAuth; ++#endif ++ db->mTrace = mTrace; ++ if( zErr || rc ){ ++ sqlite3VdbeError(p, "%s", zErr); ++ sqlite3_free(zErr); ++ if( rc==SQLITE_NOMEM ) goto no_mem; ++ goto abort_due_to_error; ++ } + break; + } + +@@ -95189,13 +99834,14 @@ case OP_IntegrityCk: { + pIn1 = &aMem[pOp->p1]; + assert( pOp->p5 nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p5) ); +- z = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot, +- (int)pnErr->u.i+1, &nErr); ++ rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot, ++ (int)pnErr->u.i+1, &nErr, &z); + sqlite3VdbeMemSetNull(pIn1); + if( nErr==0 ){ + assert( z==0 ); +- }else if( z==0 ){ +- goto no_mem; ++ }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); +@@ -95399,9 +100045,6 @@ case OP_Program: { /* jump */ + pFrame->aOp = p->aOp; + pFrame->nOp = p->nOp; + pFrame->token = pProgram->token; +-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- pFrame->anExec = p->anExec; +-#endif + #ifdef SQLITE_DEBUG + pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; + #endif +@@ -95438,9 +100081,6 @@ case OP_Program: { /* jump */ + memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8); + p->aOp = aOp = pProgram->aOp; + p->nOp = pProgram->nOp; +-#ifdef SQLITE_ENABLE_STMT_SCANSTATUS +- p->anExec = 0; +-#endif + #ifdef SQLITE_DEBUG + /* Verify that second and subsequent executions of the same trigger do not + ** try to reuse register values from the first use. */ +@@ -95580,7 +100220,7 @@ case OP_IfPos: { /* jump, in1 */ + ** 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 process. r[P1] holds the limit counter. r[P3] ++** 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 +@@ -95747,7 +100387,7 @@ case OP_AggStep1: { + /* 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 relavant parts of the sqlite3_context object */ ++ ** 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]; +@@ -95842,6 +100482,7 @@ case OP_AggFinal: { + } + sqlite3VdbeChangeEncoding(pMem, encoding); + UPDATE_MAX_BLOBSIZE(pMem); ++ REGISTER_TRACE((int)(pMem-aMem), pMem); + break; + } + +@@ -96197,7 +100838,7 @@ case OP_VDestroy: { + ** P1 is a cursor number. This opcode opens a cursor to the virtual + ** table and stores that cursor in P1. + */ +-case OP_VOpen: { ++case OP_VOpen: { /* ncycle */ + VdbeCursor *pCur; + sqlite3_vtab_cursor *pVCur; + sqlite3_vtab *pVtab; +@@ -96233,6 +100874,52 @@ case OP_VOpen: { + } + #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->p1 nDb ); ++ 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) +@@ -96244,7 +100931,7 @@ case OP_VOpen: { + ** cursor. Register P3 is used to hold the values returned by + ** sqlite3_vtab_in_first() and sqlite3_vtab_in_next(). + */ +-case OP_VInitIn: { /* out2 */ ++case OP_VInitIn: { /* out2, ncycle */ + VdbeCursor *pC; /* The cursor containing the RHS values */ + ValueList *pRhs; /* New ValueList object to put in reg[P2] */ + +@@ -96255,7 +100942,7 @@ case OP_VInitIn: { /* out2 */ + pRhs->pOut = &aMem[pOp->p3]; + pOut = out2Prerelease(p, pOp); + pOut->flags = MEM_Null; +- sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free); ++ sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree); + break; + } + #endif /* SQLITE_OMIT_VIRTUALTABLE */ +@@ -96281,7 +100968,7 @@ case OP_VInitIn: { /* out2 */ + ** + ** A jump is made to P2 if the result set after filtering would be empty. + */ +-case OP_VFilter: { /* jump */ ++case OP_VFilter: { /* jump, ncycle */ + int nArg; + int iQuery; + const sqlite3_module *pModule; +@@ -96341,11 +101028,12 @@ case OP_VFilter: { /* jump */ + ** bits (OPFLAG_LENGTHARG or OPFLAG_TYPEOFARG) but those bits are + ** unused by OP_VColumn. + */ +-case 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 ); +@@ -96363,6 +101051,9 @@ case OP_VColumn: { + 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); +@@ -96393,7 +101084,7 @@ case OP_VColumn: { + ** 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 */ ++case OP_VNext: { /* jump, ncycle */ + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + int res; +@@ -96624,7 +101315,7 @@ case OP_MaxPgcnt: { /* out2 */ + ** 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 determinitic of non-deterministic, depending on their arguments. ++** 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. +@@ -96642,7 +101333,7 @@ case OP_Function: { /* group */ + /* 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 relavant parts of the sqlite3_context object */ ++ ** reinitializes the relevant parts of the sqlite3_context object */ + pOut = &aMem[pOp->p3]; + if( pCtx->pOut != pOut ){ + pCtx->pVdbe = p; +@@ -96695,6 +101386,42 @@ case OP_ClrSubtype: { /* in1 */ + 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) + ** +@@ -96718,7 +101445,7 @@ case OP_FilterAdd: { + printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); + } + #endif +- h %= pIn1->n; ++ h %= (pIn1->n*8); + pIn1->z[h/8] |= 1<<(h&7); + break; + } +@@ -96754,7 +101481,7 @@ case OP_Filter: { /* jump */ + printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); + } + #endif +- h %= pIn1->n; ++ h %= (pIn1->n*8); + if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ + VdbeBranchTaken(1, 2); + p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++; +@@ -96976,11 +101703,13 @@ default: { /* This is really OP_Noop, OP_Explain */ + *****************************************************************************/ + } + +-#ifdef VDBE_PROFILE +- { +- u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); +- if( endTime>start ) pOrigOp->cycles += endTime - start; +- pOrigOp->cnt++; ++#if defined(VDBE_PROFILE) ++ *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); ++ pnCycle = 0; ++#elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) ++ if( pnCycle ){ ++ *pnCycle += sqlite3Hwtime(); ++ pnCycle = 0; + } + #endif + +@@ -97004,7 +101733,7 @@ default: { /* This is really OP_Noop, OP_Explain */ + } + if( opProperty==0xff ){ + /* Never happens. This code exists to avoid a harmless linkage +- ** warning aboud sqlite3VdbeRegisterDump() being defined but not ++ ** warning about sqlite3VdbeRegisterDump() being defined but not + ** used. */ + sqlite3VdbeRegisterDump(p); + } +@@ -97057,6 +101786,18 @@ abort_due_to_error: + ** 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; +@@ -97068,7 +101809,9 @@ vdbe_return: + } + #endif + p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; +- sqlite3VdbeLeave(p); ++ if( DbMaskNonZero(p->lockMask) ){ ++ sqlite3VdbeLeave(p); ++ } + assert( rc!=SQLITE_OK || nExtraDelete==0 + || sqlite3_strlike("DELETE%",p->zSql,0)!=0 + ); +@@ -97163,8 +101906,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ + /* Set the value of register r[1] in the SQL statement to integer iRow. + ** This is done directly as a performance optimization + */ +- v->aMem[1].flags = MEM_Int; +- v->aMem[1].u.i = iRow; ++ 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 +@@ -97247,7 +101989,7 @@ SQLITE_API int sqlite3_blob_open( + #endif + *ppBlob = 0; + #ifdef SQLITE_ENABLE_API_ARMOR +- if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ ++ if( !sqlite3SafetyCheckOk(db) || zTable==0 || zColumn==0 ){ + return SQLITE_MISUSE_BKPT; + } + #endif +@@ -97446,7 +102188,7 @@ blob_open_out: + if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); + sqlite3DbFree(db, pBlob); + } +- sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); ++ sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); + sqlite3DbFree(db, zErr); + sqlite3ParseObjectReset(&sParse); + rc = sqlite3ApiExit(db, rc); +@@ -97605,7 +102347,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ + ((Vdbe*)p->pStmt)->rc = SQLITE_OK; + rc = blobSeekToRow(p, iRow, &zErr); + if( rc!=SQLITE_OK ){ +- sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); ++ sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : (char*)0), zErr); + sqlite3DbFree(db, zErr); + } + assert( rc!=SQLITE_SCHEMA ); +@@ -97708,7 +102450,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ + ** 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" multipled by ++** 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 +@@ -97731,7 +102473,7 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){ + ** + ** 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 retreived from the sorter by the VDBE. The ++** incrementally as keys are retrieved from the sorter by the VDBE. The + ** MergeEngine object, described in further detail below, performs this + ** merge. + ** +@@ -97809,7 +102551,7 @@ struct SorterFile { + struct SorterList { + SorterRecord *pList; /* Linked list of records */ + u8 *aMemory; /* If non-NULL, bulk memory to hold pList */ +- int szPMA; /* Size of pList as PMA in bytes */ ++ i64 szPMA; /* Size of pList as PMA in bytes */ + }; + + /* +@@ -97894,7 +102636,7 @@ struct MergeEngine { + ** + ** Essentially, this structure contains all those fields of the VdbeSorter + ** structure for which each thread requires a separate instance. For example, +-** each thread requries its own UnpackedRecord object to unpack records in ++** each thread requeries its own UnpackedRecord object to unpack records in + ** as part of comparison operations. + ** + ** Before a background thread is launched, variable bDone is set to 0. Then, +@@ -97918,10 +102660,10 @@ typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int); + struct SortSubtask { + SQLiteThread *pThread; /* Background thread, if any */ + int bDone; /* Set if thread is finished but not joined */ ++ int nPMA; /* Number of PMAs currently in file */ + VdbeSorter *pSorter; /* Sorter that owns this sub-task */ + UnpackedRecord *pUnpacked; /* Space to unpack a record */ + SorterList list; /* List for thread to write to a PMA */ +- int nPMA; /* Number of PMAs currently in file */ + SorterCompare xCompare; /* Compare function to use */ + SorterFile file; /* Temp file for level-0 PMAs */ + SorterFile file2; /* Space for other PMAs */ +@@ -97966,7 +102708,7 @@ struct VdbeSorter { + ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. + ** aKey might point into aMap or into aBuffer. If neither of those locations + ** contain a contiguous representation of the key, then aAlloc is allocated +-** and the key is copied into aAlloc and aKey is made to poitn to aAlloc. ++** and the key is copied into aAlloc and aKey is made to point to aAlloc. + ** + ** pFd==0 at EOF. + */ +@@ -99337,7 +104079,7 @@ static int vdbeSorterFlushPMA(VdbeSorter *pSorter){ + ** 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 prefered as they use background threads - the final ++ ** sub-tasks are preferred as they use background threads - the final + ** sub-task uses the main thread. */ + for(i=0; i iPrev + i + 1) % nWorker; +@@ -99395,8 +104137,8 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( + int rc = SQLITE_OK; /* Return Code */ + SorterRecord *pNew; /* New list element */ + int bFlush; /* True to flush contents of memory to PMA */ +- int nReq; /* Bytes of memory required */ +- int nPMA; /* Bytes of PMA space required */ ++ 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 ); +@@ -99821,7 +104563,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ + + rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); + +- /* Set up the required files for pIncr. A multi-theaded IncrMerge object ++ /* 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 ){ +@@ -100461,6 +105203,8 @@ static int bytecodevtabConnect( + "p5 INT," + "comment TEXT," + "subprog TEXT," ++ "nexec INT," ++ "ncycle INT," + "stmt HIDDEN" + ");", + +@@ -100475,6 +105219,9 @@ static int bytecodevtabConnect( + ");" + }; + ++ (void)argc; ++ (void)argv; ++ (void)pzErr; + rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); +@@ -100620,7 +105367,7 @@ static int bytecodevtabColumn( + } + } + } +- i += 10; ++ i += 20; + } + } + switch( i ){ +@@ -100670,16 +105417,31 @@ static int bytecodevtabColumn( + } + break; + } +- case 10: /* tables_used.type */ ++ ++#ifdef SQLITE_ENABLE_STMT_SCANSTATUS ++ case 9: /* nexec */ ++ sqlite3_result_int(ctx, pOp->nExec); ++ break; ++ case 10: /* ncycle */ ++ sqlite3_result_int(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 11: /* tables_used.schema */ ++ case 21: /* tables_used.schema */ + sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC); + break; +- case 12: /* tables_used.name */ ++ case 22: /* tables_used.name */ + sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC); + break; +- case 13: /* tables_used.wr */ ++ case 23: /* tables_used.wr */ + sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite); + break; + } +@@ -100710,6 +105472,7 @@ static int bytecodevtabFilter( + bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor; + bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab; + int rc = SQLITE_OK; ++ (void)idxStr; + + bytecodevtabCursorClear(pCur); + pCur->iRowid = 0; +@@ -100752,7 +105515,7 @@ static int bytecodevtabBestIndex( + int rc = SQLITE_CONSTRAINT; + struct sqlite3_index_constraint *p; + bytecodevtab *pVTab = (bytecodevtab*)tab; +- int iBaseCol = pVTab->bTablesUsed ? 4 : 8; ++ int iBaseCol = pVTab->bTablesUsed ? 4 : 10; + pIdxInfo->estimatedCost = (double)100; + pIdxInfo->estimatedRows = 100; + pIdxInfo->idxNum = 0; +@@ -100799,7 +105562,8 @@ static sqlite3_module bytecodevtabModule = { + /* xSavepoint */ 0, + /* xRelease */ 0, + /* xRollbackTo */ 0, +- /* xShadowName */ 0 ++ /* xShadowName */ 0, ++ /* xIntegrity */ 0 + }; + + +@@ -101178,6 +105942,8 @@ SQLITE_PRIVATE int sqlite3JournalOpen( + ){ + 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 +@@ -101321,7 +106087,7 @@ static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){ + ** The return value from this routine is WRC_Abort to abandon the tree walk + ** and WRC_Continue to continue. + */ +-static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ ++SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3WalkExprNN(Walker *pWalker, Expr *pExpr){ + int rc; + testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); + testcase( ExprHasProperty(pExpr, EP_Reduced) ); +@@ -101330,7 +106096,9 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *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 && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; ++ if( pExpr->pLeft && sqlite3WalkExprNN(pWalker, pExpr->pLeft) ){ ++ return WRC_Abort; ++ } + if( pExpr->pRight ){ + assert( !ExprHasProperty(pExpr, EP_WinFunc) ); + pExpr = pExpr->pRight; +@@ -101354,7 +106122,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ + return WRC_Continue; + } + SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){ +- return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue; ++ return pExpr ? sqlite3WalkExprNN(pWalker,pExpr) : WRC_Continue; + } + + /* +@@ -101480,7 +106248,7 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ + } + + /* Increase the walkerDepth when entering a subquery, and +-** descrease when leaving the subquery. ++** decrease when leaving the subquery. + */ + SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){ + UNUSED_PARAMETER(pSelect); +@@ -101619,28 +106387,41 @@ static void resolveAlias( + pExpr->y.pWin->pOwner = pExpr; + } + } +- sqlite3ParserAddCleanup(pParse, +- (void(*)(sqlite3*,void*))sqlite3ExprDelete, +- pDup); ++ sqlite3ExprDeferredDelete(pParse, pDup); + } + } + + /* +-** Subqueries stores the original database, table and column names for their +-** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN". +-** Check to see if the zSpan given to this routine matches the zDb, zTab, +-** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will +-** match anything. ++** 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 ++ const char *zDb, ++ int *pbRowid + ){ + int n; + const char *zSpan; +- if( pItem->fg.eEName!=ENAME_TAB ) return 0; ++ 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) ){ +@@ -101652,9 +106433,11 @@ SQLITE_PRIVATE int sqlite3MatchEName( + return 0; + } + zSpan += n+1; +- if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){ +- return 0; ++ 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; + } + +@@ -101687,6 +106470,7 @@ SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){ + 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 + ){ +@@ -101724,6 +106508,32 @@ static void extendFJMatch( + } + } + ++/* ++** 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 */ ++ Schema *pSchema /* 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( pSchema==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 +@@ -101761,7 +106571,7 @@ static int lookupName( + ){ + int i, j; /* Loop counters */ + int cnt = 0; /* Number of matching column names */ +- int cntTab = 0; /* Number of matching table 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 */ +@@ -101838,54 +106648,66 @@ static int lookupName( + assert( pEList!=0 ); + assert( pEList->nExpr==pTab->nCol ); + for(j=0; j nExpr; j++){ +- if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){ ++ int bRowid = 0; /* True if possible rowid match */ ++ if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb, &bRowid) ){ + continue; + } +- 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); ++ 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; + } +- cnt++; +- cntTab = 2; ++ cntTab++; + pMatch = pItem; + pExpr->iColumn = j; + pEList->a[j].fg.bUsed = 1; +- hit = 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 ){ +- const char *zTabName; + if( zDb ){ + if( pTab->pSchema!=pSchema ) continue; + if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue; + } +- zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; +- assert( zTabName!=0 ); +- if( sqlite3StrICmp(zTabName, zTab)!=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, pSchema) ) continue; + } + assert( ExprUseYTab(pExpr) ); + if( IN_RENAME_OBJECT && pItem->zAlias ){ +@@ -101961,7 +106783,8 @@ static int lookupName( + assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); + if( pParse->bReturning ){ + if( (pNC->ncFlags & NC_UBaseReg)!=0 +- && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) ++ && ALWAYS(zTab==0 ++ || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) + ){ + pExpr->iTable = op!=TK_DELETE; + pTab = pParse->pTriggerTab; +@@ -102028,6 +106851,7 @@ static int lookupName( + 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{ +@@ -102061,10 +106885,10 @@ static int lookupName( + && pMatch + && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0 + && sqlite3IsRowid(zCol) +- && ALWAYS(VisibleRowid(pMatch->pTab)) ++ && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom) + ){ + cnt = 1; +- pExpr->iColumn = -1; ++ if( pMatch->fg.isNestedFrom==0 ) pExpr->iColumn = -1; + pExpr->affExpr = SQLITE_AFF_INTEGER; + } + +@@ -102223,6 +107047,7 @@ static int lookupName( + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); + pParse->checkSchema = 1; + pTopNC->nNcErr++; ++ eNewExprOp = TK_NULL; + } + assert( pFJMatch==0 ); + +@@ -102249,7 +107074,7 @@ static int lookupName( + ** If a generated column is referenced, set bits for every column + ** of the table. + */ +- if( pExpr->iColumn>=0 && pMatch!=0 ){ ++ if( pExpr->iColumn>=0 && cnt==1 && pMatch!=0 ){ + pMatch->colUsed |= sqlite3ExprColUsed(pExpr); + } + +@@ -102440,14 +107265,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ + if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ + testcase( ExprHasProperty(pExpr, EP_OuterON) ); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); +- if( pExpr->op==TK_NOTNULL ){ +- pExpr->u.zToken = "true"; +- ExprSetProperty(pExpr, EP_IsTrue); +- }else{ +- pExpr->u.zToken = "false"; +- ExprSetProperty(pExpr, EP_IsFalse); +- } +- pExpr->op = TK_TRUEFALSE; ++ pExpr->u.iValue = (pExpr->op==TK_NOTNULL); ++ pExpr->flags |= EP_IntValue; ++ pExpr->op = TK_INTEGER; ++ + for(i=0, p=pNC; p && i pNext, i++){ + p->nRef = anRef[i]; + } +@@ -102521,6 +107342,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ + 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 ); + zId = pExpr->u.zToken; + pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); + if( pDef==0 ){ +@@ -102662,6 +107484,10 @@ static int resolveExprStep(Walker *pWalker, Expr *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 +@@ -102680,6 +107506,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ + #endif + 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 ){ + Select *pSel = pNC->pWinSelect; +@@ -102708,11 +107539,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ + while( pNC2 + && sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0 + ){ +- pExpr->op2++; ++ 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 ); +@@ -102749,8 +107581,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ + assert( pNC->nRef>=nRef ); + if( nRef!=pNC->nRef ){ + ExprSetProperty(pExpr, EP_VarSelect); +- pNC->ncFlags |= NC_VarSelect; + } ++ pNC->ncFlags |= NC_Subquery; + } + break; + } +@@ -103190,7 +108022,7 @@ static int resolveOrderGroupBy( + } + for(j=0; j pEList->nExpr; j++){ + if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ +- /* Since this expresion is being changed into a reference ++ /* 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); +@@ -103243,10 +108075,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ + while( p ){ + assert( (p->selFlags & SF_Expanded)!=0 ); + assert( (p->selFlags & SF_Resolved)==0 ); +- assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */ + p->selFlags |= SF_Resolved; + +- + /* Resolve the expressions in the LIMIT and OFFSET clauses. These + ** are not allowed to refer to any names, so pass an empty NameContext. + */ +@@ -103273,6 +108103,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ + + /* Recursively resolve names in all subqueries in the FROM clause + */ ++ if( pOuterNC ) pOuterNC->nNestedSelect++; + for(i=0; i pSrc->nSrc; i++){ + SrcItem *pItem = &p->pSrc->a[i]; + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){ +@@ -103297,6 +108128,9 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ + } + } + } ++ 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. +@@ -103513,7 +108347,8 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( + return SQLITE_ERROR; + } + #endif +- sqlite3WalkExpr(&w, pExpr); ++ assert( pExpr!=0 ); ++ sqlite3WalkExprNN(&w, pExpr); + #if SQLITE_MAX_EXPR_DEPTH>0 + w.pParse->nHeight -= pExpr->nHeight; + #endif +@@ -103555,7 +108390,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames( + return WRC_Abort; + } + #endif +- sqlite3WalkExpr(&w, pExpr); ++ sqlite3WalkExprNN(&w, pExpr); + #if SQLITE_MAX_EXPR_DEPTH>0 + w.pParse->nHeight -= pExpr->nHeight; + #endif +@@ -103577,7 +108412,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames( + + /* + ** Resolve all names in all expressions of a SELECT and in all +-** decendents of the SELECT, including compounds off of p->pPrior, ++** descendants of the SELECT, including compounds off of p->pPrior, + ** subqueries in expressions, and subqueries used as FROM clause + ** terms. + ** +@@ -103704,49 +108539,122 @@ SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table *pTab, int iCol){ + */ + SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){ + int op; +- while( 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; +- assert( pExpr!=0 ); +- } + op = pExpr->op; +- if( op==TK_REGISTER ) op = pExpr->op2; +- if( op==TK_COLUMN || op==TK_AGG_COLUMN ){ +- assert( ExprUseYTab(pExpr) ); +- if( pExpr->y.pTab ){ ++ 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); +- } ++ 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); +- } ++ 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->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr ); +- return sqlite3ExprAffinity( +- pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr +- ); +- } +- if( op==TK_VECTOR ){ +- assert( ExprUseXList(pExpr) ); +- return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr); ++ 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 ){ ++ 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 || (op = pExpr->op2)==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; ii nExpr; 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 +@@ -103834,18 +108742,17 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ + while( p ){ + int op = p->op; + if( op==TK_REGISTER ) op = p->op2; +- if( op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER ){ ++ if( (op==TK_AGG_COLUMN && p->y.pTab!=0) ++ || op==TK_COLUMN || op==TK_TRIGGER ++ ){ ++ int j; + assert( ExprUseYTab(p) ); +- if( p->y.pTab!=0 ){ +- /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally +- ** a TK_COLUMN but was previously evaluated and cached in a register */ +- int j = p->iColumn; +- if( j>=0 ){ +- const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]); +- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); +- } +- break; ++ 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; +@@ -103867,11 +108774,10 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ + }else{ + Expr *pNext = p->pRight; + /* The Expr.x union is never used at the same time as Expr.pRight */ +- assert( ExprUseXList(p) ); +- assert( p->x.pList==0 || p->pRight==0 ); +- if( p->x.pList!=0 && !db->mallocFailed ){ ++ assert( !ExprUseXList(p) || p->x.pList==0 || p->pRight==0 ); ++ if( ExprUseXList(p) && p->x.pList!=0 && !db->mallocFailed ){ + int i; +- for(i=0; ALWAYS(i x.pList->nExpr); i++){ ++ for(i=0; i x.pList->nExpr; i++){ + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ + pNext = p->x.pList->a[i].pExpr; + break; +@@ -103893,7 +108799,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){ + /* + ** Return the collation sequence for the expression pExpr. If + ** there is no defined collating sequence, return a pointer to the +-** defautl collation sequence. ++** default collation sequence. + ** + ** See also: sqlite3ExprCollSeq() + ** +@@ -104023,7 +108929,7 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( + return pColl; + } + +-/* Expresssion p is a comparison operator. Return a collation sequence ++/* Expression p is a comparison operator. Return a collation sequence + ** appropriate for the comparison operator. + ** + ** This is normally just a wrapper around sqlite3BinaryCompareCollSeq(). +@@ -104180,6 +109086,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField( + */ + pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); + if( pRet ){ ++ ExprSetProperty(pRet, EP_FullSize); + pRet->iTable = nField; + pRet->iColumn = iField; + pRet->pLeft = pVector; +@@ -104430,7 +109337,9 @@ static void heightOfSelect(const Select *pSelect, int *pnHeight){ + */ + static void exprSetHeight(Expr *p){ + int nHeight = p->pLeft ? p->pLeft->nHeight : 0; +- if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight; ++ 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 ){ +@@ -104477,6 +109386,15 @@ SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + #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. + ** +@@ -104573,15 +109491,26 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees( + 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 + } +- exprSetHeight(pRoot); + } + } + +@@ -104690,9 +109619,9 @@ SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprLis + ** 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, then instead +-** of returning an AND expression, just return a constant expression with +-** a value of false. ++** 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; +@@ -104700,14 +109629,17 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ + return pRight; + }else if( pRight==0 ){ + return pLeft; +- }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) +- && !IN_RENAME_OBJECT +- ){ +- sqlite3ExprDeferredDelete(pParse, pLeft); +- sqlite3ExprDeferredDelete(pParse, pRight); +- return sqlite3Expr(db, TK_INTEGER, "0"); + }else{ +- return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); ++ u32 f = pLeft->flags | pRight->flags; ++ if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse))==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); ++ } + } + } + +@@ -104745,6 +109677,67 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction( + 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: +@@ -104867,6 +109860,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n + */ + static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ + assert( p!=0 ); ++ assert( db!=0 ); + assert( !ExprUseUValue(p) || p->u.iValue>=0 ); + assert( !ExprUseYWin(p) || !ExprUseYSub(p) ); + assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed ); +@@ -104898,17 +109892,16 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ + #endif + } + } +- if( ExprHasProperty(p, EP_MemToken) ){ +- assert( !ExprHasProperty(p, EP_IntValue) ); +- sqlite3DbFree(db, p->u.zToken); +- } + if( !ExprHasProperty(p, EP_Static) ){ +- sqlite3DbFreeNN(db, p); ++ 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 +@@ -104926,7 +109919,7 @@ SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ + /* + ** Arrange to cause pExpr to be deleted when the pParse is deleted. + ** This is similar to sqlite3ExprDelete() except that the delete is +-** deferred untilthe pParse is deleted. ++** deferred until the pParse is deleted. + ** + ** The pExpr might be deleted immediately on an OOM error. + ** +@@ -104934,8 +109927,7 @@ SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ + ** pExpr to the pParse->pConstExpr list with a register number of 0. + */ + SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){ +- pParse->pConstExpr = +- sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); ++ sqlite3ParserAddCleanup(pParse, sqlite3ExprDeleteGeneric, pExpr); + } + + /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the +@@ -105000,16 +109992,11 @@ static int dupedExprStructSize(const Expr *p, int flags){ + 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 || p->op==TK_SELECT_COLUMN +-#ifndef SQLITE_OMIT_WINDOWFUNC +- || ExprHasProperty(p, EP_WinFunc) +-#endif +- ){ ++ if( 0==flags || ExprHasProperty(p, EP_FullSize) ){ + nSize = EXPR_FULLSIZE; + }else{ + assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_OuterON) ); +- assert( !ExprHasProperty(p, EP_MemToken) ); + assert( !ExprHasVVAProperty(p, EP_NoReduce) ); + if( p->pLeft || p->x.pList ){ + nSize = EXPR_REDUCEDSIZE | EP_Reduced; +@@ -105036,56 +110023,93 @@ static int dupedExprNodeSize(const Expr *p, int flags){ + + /* + ** Return the number of bytes required to create a duplicate of the +-** expression passed as the first argument. The second argument is a +-** mask containing EXPRDUP_XXX flags. ++** 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. + ** +-** If the EXPRDUP_REDUCE flag is set, then the return value includes +-** space to duplicate all Expr nodes in the tree formed by Expr.pLeft +-** and Expr.pRight variables (but not for any structures pointed to or +-** descended from the Expr.x.pList or Expr.x.pSelect variables). ++** 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 flags){ +- int nByte = 0; +- if( p ){ +- nByte = dupedExprNodeSize(p, flags); +- if( flags&EXPRDUP_REDUCE ){ +- nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags); +- } +- } ++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; + } + + /* +-** This function is similar to sqlite3ExprDup(), except that if pzBuffer +-** is not NULL then *pzBuffer is assumed to point to a buffer large enough +-** to store the copy of expression p, the copies of p->u.zToken +-** (if applicable), and the copies of the p->pLeft and p->pRight expressions, +-** if any. Before returning, *pzBuffer is set to the first byte past the +-** portion of the buffer copied into by this function. ++** 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. + */ +-static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ ++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 */ +- u8 *zAlloc; /* Memory space from which to build Expr object */ ++ 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( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE ); ++ assert( pEdupBuf==0 || dupFlags==EXPRDUP_REDUCE ); + + /* Figure out where to write the new Expr structure. */ +- if( pzBuffer ){ +- zAlloc = *pzBuffer; ++ if( pEdupBuf ){ ++ sEdupBuf.zAlloc = pEdupBuf->zAlloc; ++#ifdef SQLITE_DEBUG ++ sEdupBuf.zEnd = pEdupBuf->zEnd; ++#endif + staticFlag = EP_Static; +- assert( zAlloc!=0 ); ++ assert( sEdupBuf.zAlloc!=0 ); ++ assert( dupFlags==EXPRDUP_REDUCE ); + }else{ +- zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags)); ++ 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 *)zAlloc; ++ pNew = (Expr *)sEdupBuf.zAlloc; ++ assert( EIGHT_BYTE_ALIGNMENT(pNew) ); + + if( pNew ){ + /* Set nNewSize to the size allocated for the structure pointed to +@@ -105094,26 +110118,31 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ + ** by the copy of the p->u.zToken string (if any). + */ + const unsigned nStructSize = dupedExprStructSize(p, dupFlags); +- const int nNewSize = nStructSize & 0xfff; +- int nToken; +- if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ +- nToken = sqlite3Strlen30(p->u.zToken) + 1; +- }else{ +- nToken = 0; ++ 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(zAlloc, p, nNewSize); ++ memcpy(sEdupBuf.zAlloc, p, nNewSize); + }else{ + u32 nSize = (u32)exprStructSize(p); +- memcpy(zAlloc, p, nSize); ++ assert( (int)(sEdupBuf.zEnd - sEdupBuf.zAlloc) >= ++ (int)EXPR_FULLSIZE+nToken ); ++ memcpy(sEdupBuf.zAlloc, p, nSize); + if( nSize flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); ++ pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); + pNew->flags |= staticFlag; + ExprClearVVAProperties(pNew); +@@ -105122,44 +110151,50 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ + } + + /* Copy the p->u.zToken string, if any. */ +- if( nToken ){ +- char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; ++ 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 ){ + +- if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){ + /* 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, dupFlags); ++ pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, ++ p->op!=TK_ORDER ? dupFlags : 0); + } +- } + +- /* Fill in pNew->pLeft and pNew->pRight. */ +- if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ +- zAlloc += dupedExprNodeSize(p, dupFlags); +- if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ +- pNew->pLeft = p->pLeft ? +- exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; +- pNew->pRight = p->pRight ? +- exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 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 */ +- if( pzBuffer ){ +- *pzBuffer = zAlloc; +- } +- }else{ +- if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ +- if( pNew->op==TK_SELECT_COLUMN ){ ++ ++ /* 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) ); ++ 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); + } +@@ -105167,6 +110202,8 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){ + } + } + } ++ if( pEdupBuf ) memcpy(pEdupBuf, &sEdupBuf, sizeof(sEdupBuf)); ++ assert( sEdupBuf.zAlloc <= sEdupBuf.zEnd ); + return pNew; + } + +@@ -105431,11 +110468,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags) + ** 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(). This routine +-** may not be used with an ExprList obtained from sqlite3ExprListDup(). +-** Reason: This routine assumes that the number of slots in pList->a[] +-** is a power of two. That is true for sqlite3ExprListAppend() returns +-** but is not necessarily true from the return value of sqlite3ExprListDup(). ++** 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 +@@ -105689,16 +110722,20 @@ 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); +- sqlite3DbFree(db, pItem->zEName); ++ if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName); + pItem++; + }while( --i>0 ); +- sqlite3DbFreeNN(db, pList); ++ 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 +@@ -105767,7 +110804,7 @@ SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ + ** and 0 if it is FALSE. + */ + SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ +- pExpr = sqlite3ExprSkipCollate((Expr*)pExpr); ++ pExpr = sqlite3ExprSkipCollateAndLikely((Expr*)pExpr); + assert( pExpr->op==TK_TRUEFALSE ); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 +@@ -105954,12 +110991,17 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ + } + + /* +-** Check pExpr to see if it is an invariant constraint on data source pSrc. ++** 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 invariant constraint, the following must be true: ++** To be an single-source constraint, the following must be true: + ** + ** (1) pExpr cannot refer to any table other than pSrc->iCursor. + ** +@@ -105970,13 +111012,31 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ + ** + ** (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. ++** (4b) and specifically the ON clause associated with the LEFT JOIN. + ** + ** (5) If pSrc is not the right operand of a LEFT JOIN or the left + ** operand of a RIGHT JOIN, then pExpr must be from the WHERE + ** clause, not an ON clause. ++** ++** (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 sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){ ++SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint( ++ Expr *pExpr, /* The constraint */ ++ const SrcList *pSrcList, /* Complete FROM clause */ ++ int iSrc /* Which element of pSrcList to use */ ++){ ++ const SrcItem *pSrc = &pSrcList->a[iSrc]; + if( pSrc->fg.jointype & JT_LTORJ ){ + return 0; /* rule (3) */ + } +@@ -105986,6 +111046,19 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc + }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; jj w.iJoin==pSrcList->a[jj].iCursor ){ ++ if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){ ++ return 0; /* restriction (6) */ ++ } ++ break; ++ } ++ } ++ } + return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */ + } + +@@ -106162,9 +111235,10 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ + case TK_COLUMN: + assert( ExprUseYTab(p) ); + return ExprHasProperty(p, EP_CanBeNull) || +- p->y.pTab==0 || /* Reference to column of index on expression */ ++ NEVER(p->y.pTab==0) || /* Reference to column of index on expr */ + (p->iColumn>=0 + && p->y.pTab->aCol!=0 /* Possible due to prior error */ ++ && ALWAYS(p->iColumn y.pTab->nCol) + && p->y.pTab->aCol[p->iColumn].notNull==0); + default: + return 1; +@@ -106224,11 +111298,32 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){ + 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; ii nCol; iCol++){ ++ if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break; ++ } ++ if( iCol==pTab->nCol ){ ++ return azOpt[ii]; ++ } ++ } ++ return 0; ++} ++ + /* + ** pX is the RHS of an IN operator. If pX is a SELECT statement + ** that can be simplified to a direct table access, then return + ** a pointer to the SELECT statement. If pX is not a SELECT statement, +-** or if the SELECT statement needs to be manifested into a transient ++** or if the SELECT statement needs to be materialized into a transient + ** table, then return NULL. + */ + #ifndef SQLITE_OMIT_SUBQUERY +@@ -106324,7 +111419,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ + ** 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 epheremal table. ++** populated ephemeral table. + ** IN_INDEX_NOOP - No cursor was allocated. The IN operator must be + ** implemented as a sequence of comparisons. + ** +@@ -106337,7 +111432,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ + ** 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 +-** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag ++** 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. + ** +@@ -106349,12 +111444,12 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ + ** + ** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate + ** through the set members) then the b-tree must not contain duplicates. +-** An epheremal table will be created unless the selected columns are guaranteed ++** 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 epheremal table must ++** 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. + ** +@@ -106514,7 +111609,6 @@ SQLITE_PRIVATE int sqlite3FindInIndex( + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); + int j; + +- assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); + for(j=0; j aiColumn[j]!=pRhs->iColumn ) continue; + assert( pIdx->azColl[j] ); +@@ -106688,7 +111782,7 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){ + ** 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 ephermeral table is returned. The first time the ephemeral ++** 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. +@@ -106872,6 +111966,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( + sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO); + } + if( addrOnce ){ ++ sqlite3VdbeAddOp1(v, OP_NullRow, iTab); + sqlite3VdbeJumpHere(v, addrOnce); + /* Subroutine return */ + assert( ExprUseYSub(pExpr) ); +@@ -106907,6 +112002,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ + 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 ); +@@ -106959,8 +112057,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ + ** In both cases, the query is augmented with "LIMIT 1". Any + ** preexisting limit is discarded in place of the new LIMIT 1. + */ +- ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY %d", ++ 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; +@@ -106985,7 +112084,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ + pLimit = sqlite3PExpr(pParse, TK_NE, + sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit); + } +- sqlite3ExprDelete(db, pSel->pLimit->pLeft); ++ sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft); + pSel->pLimit->pLeft = pLimit; + }else{ + /* If there is no pre-existing limit add a limit of 1 */ +@@ -107003,6 +112102,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ + if( addrOnce ){ + sqlite3VdbeJumpHere(v, addrOnce); + } ++ sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); + + /* Subroutine return */ + assert( ExprUseYSub(pExpr) ); +@@ -107411,6 +112511,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( + ){ + int iAddr; + Vdbe *v = pParse->pVdbe; ++ int nErr = pParse->nErr; + assert( v!=0 ); + assert( pParse->iSelfTab!=0 ); + if( pParse->iSelfTab>0 ){ +@@ -107423,6 +112524,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn( + 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 */ + +@@ -107438,10 +112540,8 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( + ){ + Column *pCol; + assert( v!=0 ); +- if( pTab==0 ){ +- sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut); +- return; +- } ++ 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)); +@@ -107497,10 +112597,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( + 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 = sqlite3VdbeGetOp(pParse->pVdbe,-1); ++ 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; + } +@@ -107529,7 +112632,7 @@ static void exprToRegister(Expr *pExpr, int iReg){ + + /* + ** Evaluate an expression (either a vector or a scalar expression) and store +-** the result in continguous temporary registers. Return the index of ++** 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 +@@ -107568,8 +112671,8 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ + ** so that a subsequent copy will not be merged into this one. + */ + static void setDoNotMergeFlagOnCopy(Vdbe *v){ +- if( sqlite3VdbeGetOp(v, -1)->opcode==OP_Copy ){ +- sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */ ++ if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){ ++ sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergeable */ + } + } + +@@ -107659,13 +112762,13 @@ static int exprCodeInlineFunction( + } + + case INLINEFUNC_implies_nonnull_row: { +- /* REsult of sqlite3ExprImpliesNonNullRow() */ ++ /* 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), ++ sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable,1), + target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); +@@ -107678,10 +112781,13 @@ static int exprCodeInlineFunction( + ** the type affinity of the argument. This is used for testing of + ** the SQLite type logic. + */ +- const char *azAff[] = { "blob", "text", "numeric", "integer", "real" }; ++ 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; +@@ -107691,6 +112797,99 @@ static int exprCodeInlineFunction( + return target; + } + ++/* ++** 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; ++ } ++ ++ 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 */ ++} ++ ++ ++/* ++** Expresion 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 +@@ -107719,25 +112918,44 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) + 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 && pExpr->iAgg nColumn ); ++ 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 ){ +- assert( pCol->iMem>0 ); +- return pCol->iMem; ++ return AggInfoColumnReg(pAggInfo, pExpr->iAgg); + }else if( pAggInfo->useSortingIdx ){ + Table *pTab = pCol->pTab; + sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, + pCol->iSorterColumn, target); +- if( pCol->iColumn<0 ){ ++ if( pTab==0 ){ ++ /* No comment added */ ++ }else if( pCol->iColumn<0 ){ + VdbeComment((v,"%s.rowid",pTab->zName)); + }else{ + VdbeComment((v,"%s.%s", +@@ -107747,6 +112965,11 @@ expr_code_doover: + } + } + 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 +@@ -107757,20 +112980,17 @@ expr_code_doover: + 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 +- ** expresssion. However, make sure the constant has the correct ++ ** 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) ); +- if( pExpr->y.pTab ){ +- aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); +- }else{ +- aff = pExpr->affExpr; +- } ++ 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"; ++ 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, +@@ -107829,13 +113049,16 @@ expr_code_doover: + 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); +- if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){ +- sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); +- } + return iReg; + } + case TK_INTEGER: { +@@ -107902,11 +113125,8 @@ expr_code_doover: + #ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ +- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); +- if( inReg!=target ){ +- sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); +- inReg = target; +- } ++ sqlite3ExprCode(pParse, pExpr->pLeft, target); ++ assert( inReg==target ); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3VdbeAddOp2(v, OP_Cast, target, + sqlite3AffinityType(pExpr->u.zToken, 0)); +@@ -108049,7 +113269,7 @@ expr_code_doover: + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr); + }else{ +- return pInfo->aFunc[pExpr->iAgg].iMem; ++ return AggInfoFuncReg(pInfo, pExpr->iAgg); + } + break; + } +@@ -108091,7 +113311,7 @@ expr_code_doover: + sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); + break; + } +- if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ ++ 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, +@@ -108117,10 +113337,10 @@ expr_code_doover: + r1 = sqlite3GetTempRange(pParse, nFarg); + } + +- /* For length() and typeof() functions with a column argument, ++ /* For length() and typeof() and octet_length() functions, + ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG +- ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data +- ** loading. ++ ** or OPFLAG_TYPEOFARG or OPFLAG_BYTELENARG respectively, to avoid ++ ** unnecessary data loading. + */ + if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ + u8 exprOp; +@@ -108130,14 +113350,16 @@ expr_code_doover: + if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ + assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); + assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); +- testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); +- pFarg->a[0].pExpr->op2 = +- pDef->funcFlags & (OPFLAG_LENGTHARG|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_DUP|SQLITE_ECEL_FACTOR); ++ sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, SQLITE_ECEL_FACTOR); + }else{ + r1 = 0; + } +@@ -108238,17 +113460,16 @@ expr_code_doover: + return target; + } + case TK_COLLATE: { +- if( !ExprHasProperty(pExpr, EP_Collate) +- && ALWAYS(pExpr->pLeft) +- && pExpr->pLeft->op==TK_FUNCTION +- ){ +- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); +- if( inReg!=target ){ +- sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); +- inReg = target; +- } +- sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg); +- return inReg; ++ 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 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. */ +@@ -108334,16 +113555,34 @@ expr_code_doover: + case TK_IF_NULL_ROW: { + int addrINR; + u8 okConstFactor = pParse->okConstFactor; +- addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); +- /* Temporarily disable factoring of constant expressions, since +- ** even though expressions may appear to be constant, they are not +- ** really constant because they originate from the right-hand side +- ** of a LEFT JOIN. */ +- pParse->okConstFactor = 0; +- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); ++ AggInfo *pAggInfo = pExpr->pAggInfo; ++ if( pAggInfo ){ ++ assert( pExpr->iAgg>=0 && pExpr->iAgg nColumn ); ++ 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); +- sqlite3VdbeChangeP3(v, addrINR, inReg); + break; + } + +@@ -108475,9 +113714,9 @@ expr_code_doover: + ** 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 ++** 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 whereever it wants. The register where the expression ++** 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 +@@ -108490,6 +113729,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( + ){ + ExprList *p; + assert( ConstFactorOk(pParse) ); ++ assert( regDest!=0 ); + p = pParse->pConstExpr; + if( regDest<0 && p ){ + struct ExprList_item *pItem; +@@ -108580,7 +113820,11 @@ SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + if( inReg!=target ){ + u8 op; +- if( ALWAYS(pExpr) && ExprHasProperty(pExpr,EP_Subquery) ){ ++ 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; +@@ -108675,7 +113919,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( + if( inReg!=target+i ){ + VdbeOp *pOp; + if( copyOp==OP_Copy +- && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==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 */ +@@ -108874,6 +114118,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int + assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); + assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); ++ sqlite3VdbeTypeofColumn(v, r1); + sqlite3VdbeAddOp2(v, op, r1, dest); + VdbeCoverageIf(v, op==TK_ISNULL); + VdbeCoverageIf(v, op==TK_NOTNULL); +@@ -109048,6 +114293,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int + case TK_ISNULL: + case TK_NOTNULL: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); ++ 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); +@@ -109201,7 +114447,13 @@ SQLITE_PRIVATE int sqlite3ExprCompare( + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){ + return 1; + } +- return 2; ++ 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) ); +@@ -109291,8 +114543,8 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB + */ + SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){ + return sqlite3ExprCompare(0, +- sqlite3ExprSkipCollateAndLikely(pA), +- sqlite3ExprSkipCollateAndLikely(pB), ++ sqlite3ExprSkipCollate(pA), ++ sqlite3ExprSkipCollate(pB), + iTab); + } + +@@ -109385,7 +114637,7 @@ static int exprImpliesNotNull( + ** pE1: x!=123 pE2: x IS NOT NULL Result: true + ** pE1: x!=?1 pE2: x IS NOT NULL Result: true + ** pE1: x IS NULL pE2: x IS NOT NULL Result: false +-** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false ++** pE1: x IS ?2 pE2: x IS NOT NULL Result: false + ** + ** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has + ** Expr.iTable<0 then assume a table number given by iTab. +@@ -109422,11 +114674,29 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr( + 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. +@@ -109435,28 +114705,33 @@ 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_OR: + case TK_VECTOR: +- case TK_CASE: +- case TK_IN: + 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_OR ); + testcase( pExpr->op==TK_VECTOR ); +- testcase( pExpr->op==TK_CASE ); +- testcase( pExpr->op==TK_IN ); + 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; +@@ -109464,21 +114739,38 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + } + return WRC_Prune; + ++ case TK_OR: + case TK_AND: +- if( pWalker->eCode==0 ){ ++ /* 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); +- if( pWalker->eCode ){ +- pWalker->eCode = 0; +- sqlite3WalkExpr(pWalker, pExpr->pRight); +- } + } + return WRC_Prune; + + case TK_BETWEEN: +- if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){ +- assert( pWalker->eCode ); +- return WRC_Abort; +- } ++ /* 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 +@@ -109503,10 +114795,10 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) ); + assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) ); + if( (pLeft->op==TK_COLUMN +- && pLeft->y.pTab!=0 ++ && ALWAYS(pLeft->y.pTab!=0) + && IsVirtual(pLeft->y.pTab)) + || (pRight->op==TK_COLUMN +- && pRight->y.pTab!=0 ++ && ALWAYS(pRight->y.pTab!=0) + && IsVirtual(pRight->y.pTab)) + ){ + return WRC_Prune; +@@ -109540,7 +114832,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + ** be non-NULL, then the LEFT JOIN can be safely converted into an + ** ordinary join. + */ +-SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ ++SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){ + Walker w; + p = sqlite3ExprSkipCollateAndLikely(p); + if( p==0 ) return 0; +@@ -109548,7 +114840,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ + p = p->pLeft; + }else{ + while( p->op==TK_AND ){ +- if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1; ++ if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1; + p = p->pRight; + } + } +@@ -109556,6 +114848,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ + w.xSelectCallback = 0; + w.xSelectCallback2 = 0; + w.eCode = 0; ++ w.mWFlags = isRJ!=0; + w.u.iCur = iTab; + sqlite3WalkExpr(&w, p); + return w.eCode; +@@ -109616,7 +114909,7 @@ SQLITE_PRIVATE int sqlite3ExprCoveredByIndex( + } + + +-/* Structure used to pass information throught the Walker in order to ++/* Structure used to pass information throughout the Walker in order to + ** implement sqlite3ReferencesSrcList(). + */ + struct RefSrcList { +@@ -109711,6 +115004,7 @@ static int exprRefToSrcList(Walker *pWalker, Expr *pExpr){ + 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; +@@ -109722,12 +115016,18 @@ SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList + 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 +- sqlite3DbFree(pParse->db, x.aiExclude); ++ if( x.aiExclude ) sqlite3DbNNFreeNN(pParse->db, x.aiExclude); + if( w.eCode & 0x01 ){ + return 1; + }else if( w.eCode ){ +@@ -109745,10 +115045,8 @@ SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList + ** it does, make a copy. This is done because the pExpr argument is + ** subject to change. + ** +-** The copy is stored on pParse->pConstExpr with a register number of 0. +-** This will cause the expression to be deleted automatically when the +-** Parse object is destroyed, but the zero register number means that it +-** will not generate any code in the preamble. ++** 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)) +@@ -109758,10 +115056,11 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ + int iAgg = pExpr->iAgg; + Parse *pParse = pWalker->pParse; + sqlite3 *db = pParse->db; +- assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION ); +- if( pExpr->op==TK_AGG_COLUMN ){ +- assert( iAgg>=0 && iAgg nColumn ); +- if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){ ++ assert( iAgg>=0 ); ++ if( pExpr->op!=TK_AGG_FUNCTION ){ ++ if( iAgg nColumn ++ && pAggInfo->aCol[iAgg].pCExpr==pExpr ++ ){ + pExpr = sqlite3ExprDup(db, pExpr, 0); + if( pExpr ){ + pAggInfo->aCol[iAgg].pCExpr = pExpr; +@@ -109769,8 +115068,10 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ + } + } + }else{ +- assert( iAgg>=0 && iAgg nFunc ); +- if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ ++ assert( pExpr->op==TK_AGG_FUNCTION ); ++ if( ALWAYS(iAgg nFunc) ++ && pAggInfo->aFunc[iAgg].pFExpr==pExpr ++ ){ + pExpr = sqlite3ExprDup(db, pExpr, 0); + if( pExpr ){ + pAggInfo->aFunc[iAgg].pFExpr = pExpr; +@@ -109825,6 +115126,74 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ + 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; ++ ++ assert( pAggInfo->iFirstReg==0 ); ++ pCol = pAggInfo->aCol; ++ for(k=0; k nColumn; 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; ++ } ++ 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; j pExpr; ++ 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; ++ } ++ pExpr->iAgg = (i16)k; ++} ++ + /* + ** This is the xExprCallback for a tree walker. It is used to + ** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates +@@ -109838,87 +115207,76 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + 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; i nSrc; 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.iAgg nColumn ); ++ 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; i nSrc; i++, pItem++){ +- struct AggInfo_col *pCol; + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + if( pExpr->iTable==pItem->iCursor ){ +- /* If we reach this point, it means that pExpr refers to a table +- ** that is in the FROM clause of the aggregate query. +- ** +- ** Make an entry for the column in pAggInfo->aCol[] if there +- ** is not an entry there already. +- */ +- int k; +- pCol = pAggInfo->aCol; +- for(k=0; k nColumn; k++, pCol++){ +- if( pCol->iTable==pExpr->iTable && +- pCol->iColumn==pExpr->iColumn ){ +- break; +- } +- } +- if( (k>=pAggInfo->nColumn) +- && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 +- ){ +- pCol = &pAggInfo->aCol[k]; +- assert( ExprUseYTab(pExpr) ); +- pCol->pTab = pExpr->y.pTab; +- pCol->iTable = pExpr->iTable; +- pCol->iColumn = pExpr->iColumn; +- pCol->iMem = ++pParse->nMem; +- pCol->iSorterColumn = -1; +- pCol->pCExpr = pExpr; +- if( pAggInfo->pGroupBy ){ +- int j, n; +- ExprList *pGB = pAggInfo->pGroupBy; +- struct ExprList_item *pTerm = pGB->a; +- n = pGB->nExpr; +- for(j=0; j pExpr; +- 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++; +- } +- } +- /* There is now an entry for pExpr in pAggInfo->aCol[] (either +- ** because it was there before or because we just created it). +- ** Convert the pExpr to be a TK_AGG_COLUMN referring to that +- ** pAggInfo->aCol[] entry. +- */ +- ExprSetVVAProperty(pExpr, EP_NoReduce); +- pExpr->pAggInfo = pAggInfo; +- pExpr->op = TK_AGG_COLUMN; +- pExpr->iAgg = (i16)k; ++ findOrCreateAggInfoColumn(pParse, pAggInfo, pExpr); + break; + } /* endif pExpr->iTable==pItem->iCursor */ + } /* end loop over pSrcList */ + } +- return WRC_Prune; ++ 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; + for(i=0; i nFunc; i++, pItem++){ +- if( pItem->pFExpr==pExpr ) break; ++ if( NEVER(pItem->pFExpr==pExpr) ) break; + if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){ + break; + } +@@ -109929,15 +115287,44 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + 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; +- pItem->iMem = ++pParse->nMem; + assert( ExprUseUToken(pExpr) ); ++ nArg = pExpr->x.pList ? pExpr->x.pList->nExpr : 0; + pItem->pFunc = sqlite3FindFunction(pParse->db, +- pExpr->u.zToken, +- pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); +- if( pExpr->flags & EP_Distinct ){ ++ 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; +@@ -110061,6 +115448,37 @@ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ + 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->nMem nMem = 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; i nExpr; 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() +@@ -110080,6 +115498,14 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){ + return 0; + } + } ++ if( pParse->pConstExpr ){ ++ ExprList *pList = pParse->pConstExpr; ++ for(i=0; i nExpr; i++){ ++ int iReg = pList->a[i].u.iConstExprReg; ++ if( iReg==0 ) continue; ++ if( iReg>=iFirst && iReg<=iLast ) return 0; ++ } ++ } + return 1; + } + #endif /* SQLITE_DEBUG */ +@@ -110534,14 +115960,19 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ + /* 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*'", ++ " WHERE quick_check GLOB 'CHECK*'" ++ " OR quick_check GLOB 'NULL*'" ++ " OR quick_check GLOB 'non-* value in*'", + zTab, zDb + ); + } +@@ -110630,7 +116061,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + 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; +- pNew->nTabRef = 1; ++ assert( pNew->nTabRef==1 ); + + exit_begin_add_column: + sqlite3SrcListDelete(db, pSrc); +@@ -110829,13 +116260,14 @@ static void renameTokenCheckAll(Parse *pParse, const void *pPtr){ + assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); + if( pParse->nErr==0 ){ + const RenameToken *p; +- u8 i = 0; ++ u32 i = 1; + for(p=pParse->pRename; p; p=p->pNext){ + if( p->p ){ + assert( p->p!=pPtr ); +- i += *(u8*)(p->p); ++ i += *(u8*)(p->p) | 1; + } + } ++ assert( i>0 ); + } + } + #else +@@ -111134,7 +116566,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ + } + + /* +-** An error occured while parsing or otherwise processing a database ++** 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 +@@ -111366,6 +116798,19 @@ static int renameEditSql( + return rc; + } + ++/* ++** Set all pEList->a[].fg.eEName fields in the expression-list to val. ++*/ ++static void renameSetENames(ExprList *pEList, int val){ ++ if( pEList ){ ++ int i; ++ for(i=0; i nExpr; i++){ ++ assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME ); ++ pEList->a[i].fg.eEName = val; ++ } ++ } ++} ++ + /* + ** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming + ** it was read from the schema of database zDb. Return SQLITE_OK if +@@ -111413,7 +116858,17 @@ static int renameResolveTrigger(Parse *pParse){ + 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 ); +@@ -112632,9 +118087,9 @@ static void openStatTable( + typedef struct StatAccum StatAccum; + typedef struct StatSample StatSample; + struct StatSample { +- tRowcnt *anEq; /* sqlite_stat4.nEq */ + tRowcnt *anDLt; /* sqlite_stat4.nDLt */ + #ifdef SQLITE_ENABLE_STAT4 ++ tRowcnt *anEq; /* sqlite_stat4.nEq */ + tRowcnt *anLt; /* sqlite_stat4.nLt */ + union { + i64 iRowid; /* Rowid in main table of the key */ +@@ -112792,9 +118247,9 @@ static void statInit( + + /* Allocate the space required for the StatAccum object */ + n = sizeof(*p) +- + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */ +- + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */ ++ + 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[] */ +@@ -112815,9 +118270,9 @@ static void statInit( + p->nKeyCol = nKeyCol; + p->nSkipAhead = 0; + p->current.anDLt = (tRowcnt*)&p[1]; +- p->current.anEq = &p->current.anDLt[nColUp]; + + #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 */ +@@ -113084,7 +118539,9 @@ static void statPush( + + if( p->nRow==0 ){ + /* This is the first call to this function. Do initialization. */ ++#ifdef SQLITE_ENABLE_STAT4 + for(i=0; i nCol; i++) p->current.anEq[i] = 1; ++#endif + }else{ + /* Second and subsequent calls get processed here */ + #ifdef SQLITE_ENABLE_STAT4 +@@ -113093,15 +118550,17 @@ static void statPush( + + /* 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; i current.anEq[i]++; + } ++#endif + for(i=iChng; i nCol; i++){ + p->current.anDLt[i]++; + #ifdef SQLITE_ENABLE_STAT4 + if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i]; +-#endif + p->current.anEq[i] = 1; ++#endif + } + } + +@@ -113235,7 +118694,9 @@ static void statGet( + 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] ); ++#endif + } + sqlite3ResultStrAccum(context, &sStat); + } +@@ -113321,6 +118782,7 @@ static void analyzeVdbeCommentIndexWithColumnName( + 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)); +@@ -113361,11 +118823,15 @@ static void analyzeOneTable( + 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 + +- pParse->nMem = MAX(pParse->nMem, iMem); ++ sqlite3TouchRegister(pParse, iMem); ++ assert( sqlite3NoTempsInRange(pParse, regNewRowid, iMem) ); + v = sqlite3GetVdbe(pParse); + if( v==0 || NEVER(pTab==0) ){ + return; +@@ -113471,7 +118937,7 @@ static void analyzeOneTable( + ** the regPrev array and a trailing rowid (the rowid slot is required + ** when building a record to insert into the sample column of + ** the sqlite_stat4 table. */ +- pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); ++ sqlite3TouchRegister(pParse, regPrev+nColTest); + + /* Open a read-only cursor on the index being analyzed. */ + assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); +@@ -113643,7 +119109,35 @@ static void analyzeOneTable( + int addrIsNull; + u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; + +- pParse->nMem = MAX(pParse->nMem, regCol+nCol); ++ 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); +@@ -113724,6 +119218,11 @@ static void analyzeDatabase(Parse *pParse, int iDb){ + 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); + } +@@ -113886,6 +119385,16 @@ static void decodeIntArray( + while( z[0]!=0 && z[0]!=' ' ) z++; + while( z[0]==' ' ) z++; + } ++ ++ /* Set the bLowQual flag if the peak number of rows obtained ++ ** from a full equality match is so large that a full table scan ++ ** seems likely to be faster than using the index. ++ */ ++ if( aLog[0] > 66 /* Index has more than 100 rows */ ++ && aLog[0] <= aLog[nOut-1] /* And only a single value seen */ ++ ){ ++ pIndex->bLowQual = 1; ++ } + } + } + +@@ -113964,6 +119473,8 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ + ** 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; +@@ -113973,7 +119484,7 @@ SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){ + } + sqlite3DbFree(db, pIdx->aSample); + } +- if( db && db->pnBytesFreed==0 ){ ++ if( db->pnBytesFreed==0 ){ + pIdx->nSample = 0; + pIdx->aSample = 0; + } +@@ -114109,6 +119620,10 @@ static int loadStatTbl( + 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; +@@ -114116,6 +119631,7 @@ static int loadStatTbl( + nIdxCol = pIdx->nColumn; + } + pIdx->nSampleCol = nIdxCol; ++ pIdx->mxSample = nSample; + nByte = sizeof(IndexSample) * nSample; + nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; + nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ +@@ -114155,6 +119671,11 @@ static int loadStatTbl( + 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; +@@ -114167,14 +119688,15 @@ static int loadStatTbl( + decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0); + decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0); + +- /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer. ++ /* 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. Adding the two 0x00 bytes prevents this from causing ++ ** 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 + 2); ++ pSample->p = sqlite3DbMallocZero(db, pSample->n + 8); + if( pSample->p==0 ){ + sqlite3_finalize(pStmt); + return SQLITE_NOMEM_BKPT; +@@ -114198,11 +119720,12 @@ static int loadStat4(sqlite3 *db, const char *zDb){ + const Table *pStat4; + + assert( db->lookaside.bDisable ); +- if( (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0 ++ 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", ++ "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx COLLATE nocase", + "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", + zDb + ); +@@ -114392,7 +119915,7 @@ static void attachFunc( + char *zErr = 0; + unsigned int flags; + Db *aNew; /* New array of Db pointers */ +- Db *pNew; /* Db object for the newly attached database */ ++ Db *pNew = 0; /* Db object for the newly attached database */ + char *zErrDyn = 0; + sqlite3_vfs *pVfs; + +@@ -114412,13 +119935,26 @@ static void attachFunc( + /* 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; +- pNew = &db->aDb[db->init.iDb]; +- if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); +- pNew->pBt = 0; +- pNew->pSchema = 0; +- rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); ++ 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 + ** +@@ -114504,6 +120040,11 @@ static void attachFunc( + if( rc==SQLITE_OK && pNew->zDbSName==0 ){ + rc = SQLITE_NOMEM_BKPT; + } ++ ++ /* Handle KEY parameter. */ ++ if( rc==SQLITE_OK ){ ++ rc = sqlite3mcHandleAttachKey(db, zName, zPath, argv[2], &zErrDyn); ++ } + sqlite3_free_filename( zPath ); + + /* If the file was opened successfully, read the schema for the new database. +@@ -114531,7 +120072,7 @@ static void attachFunc( + } + #endif + if( rc ){ +- if( !REOPEN_AS_MEMDB(db) ){ ++ if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){ + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ +@@ -114648,6 +120189,8 @@ static void codeAttach( + 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; +@@ -115116,7 +120659,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck( + sqlite3 *db = pParse->db; + int rc; + +- /* Don't do any authorization checks if the database is initialising ++ /* 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 ); +@@ -115323,6 +120866,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){ + SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ + sqlite3 *db; + Vdbe *v; ++ int iDb, i; + + assert( pParse->pToplevel==0 ); + db = pParse->db; +@@ -115352,7 +120896,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ + if( pParse->bReturning ){ + Returning *pReturning = pParse->u1.pReturning; + int addrRewind; +- int i; + int reg; + + if( pReturning->nRetCol ){ +@@ -115389,76 +120932,66 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ + ** transaction on each used database and to verify the schema cookie + ** on each used database. + */ +- if( db->mallocFailed==0 +- && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr) +- ){ +- int iDb, i; +- assert( 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( ++iDb nDb ); ++ 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( ++iDb nDb ); + #ifndef SQLITE_OMIT_VIRTUALTABLE +- for(i=0; i nVtabLock; i++){ +- char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); +- sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); +- } +- pParse->nVtabLock = 0; ++ for(i=0; i nVtabLock; i++){ ++ char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); ++ sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); ++ } ++ pParse->nVtabLock = 0; + #endif + +- /* Once all the cookies have been verified and transactions opened, +- ** obtain the required table-locks. This is a no-op unless the +- ** shared-cache feature is enabled. +- */ +- codeTableLocks(pParse); ++#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. +- */ +- sqlite3AutoincrementBegin(pParse); ++ /* Initialize any AUTOINCREMENT data structures required. ++ */ ++ if( pParse->pAinc ) sqlite3AutoincrementBegin(pParse); + +- /* Code constant expressions that where factored out of inner loops. +- ** +- ** The pConstExpr list might also contain expressions that we simply +- ** want to keep around until the Parse object is deleted. Such +- ** expressions have iConstExprReg==0. Do not generate code for +- ** those expressions, of course. +- */ +- if( pParse->pConstExpr ){ +- ExprList *pEL = pParse->pConstExpr; +- pParse->okConstFactor = 0; +- for(i=0; i nExpr; i++){ +- int iReg = pEL->a[i].u.iConstExprReg; +- if( iReg>0 ){ +- sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg); +- } +- } ++ /* Code constant expressions that were factored out of inner loops. ++ */ ++ if( pParse->pConstExpr ){ ++ ExprList *pEL = pParse->pConstExpr; ++ pParse->okConstFactor = 0; ++ for(i=0; i nExpr; i++){ ++ assert( pEL->a[i].u.iConstExprReg>0 ); ++ sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); + } ++ } + +- if( pParse->bReturning ){ +- Returning *pRet = pParse->u1.pReturning; +- if( pRet->nRetCol ){ +- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol); +- } ++ if( pParse->bReturning ){ ++ Returning *pRet = pParse->u1.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); + } ++ ++ /* Finally, jump back to the beginning of the executable code. */ ++ sqlite3VdbeGoto(v, 1); + } + + /* Get the VDBE program ready for execution +@@ -115497,6 +121030,7 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ + 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); +@@ -115643,7 +121177,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( + /* If zName is the not the name of a table in the schema created using + ** CREATE, then check to see if it is the name of an virtual table that + ** can be an eponymous virtual table. */ +- if( pParse->disableVtab==0 && db->init.busy==0 ){ ++ 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); +@@ -115656,7 +121190,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable( + #endif + if( flags & LOCATE_NOERR ) return 0; + pParse->checkSchema = 1; +- }else if( IsVirtual(p) && pParse->disableVtab ){ ++ }else if( IsVirtual(p) && (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)!=0 ){ + p = 0; + } + +@@ -115912,7 +121446,7 @@ SQLITE_PRIVATE void sqlite3ColumnSetExpr( + */ + SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){ + if( pCol->iDflt==0 ) return 0; +- if( NEVER(!IsOrdinaryTable(pTab)) ) return 0; ++ if( !IsOrdinaryTable(pTab) ) return 0; + if( NEVER(pTab->u.tab.pDfltList==0) ) return 0; + if( NEVER(pTab->u.tab.pDfltList->nExpr iDflt) ) return 0; + return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; +@@ -115944,7 +121478,7 @@ SQLITE_PRIVATE void sqlite3ColumnSetColl( + } + + /* +-** Return the collating squence name for a column ++** Return the collating sequence name for a column + */ + SQLITE_PRIVATE const char *sqlite3ColumnColl(Column *pCol){ + const char *z; +@@ -115965,16 +121499,17 @@ 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; i nCol; i++, pCol++){ + assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) ); + sqlite3DbFree(db, pCol->zCnName); + } +- sqlite3DbFree(db, pTable->aCol); ++ sqlite3DbNNFreeNN(db, pTable->aCol); + if( IsOrdinaryTable(pTable) ){ + sqlite3ExprListDelete(db, pTable->u.tab.pDfltList); + } +- if( db==0 || db->pnBytesFreed==0 ){ ++ if( db->pnBytesFreed==0 ){ + pTable->aCol = 0; + pTable->nCol = 0; + if( IsOrdinaryTable(pTable) ){ +@@ -116011,7 +121546,8 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ + ** 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; +- if( db && !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){ ++ assert( db!=0 ); ++ if( !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){ + nLookaside = sqlite3LookasideUsed(db, 0); + } + #endif +@@ -116021,7 +121557,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ + pNext = pIndex->pNext; + assert( pIndex->pSchema==pTable->pSchema + || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) ); +- if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){ ++ if( db->pnBytesFreed==0 && !IsVirtual(pTable) ){ + char *zName = pIndex->zName; + TESTONLY ( Index *pOld = ) sqlite3HashInsert( + &pIndex->pSchema->idxHash, zName, 0 +@@ -116035,7 +121571,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ + if( IsOrdinaryTable(pTable) ){ + sqlite3FkDelete(db, pTable); + } +-#ifndef SQLITE_OMIT_VIRTUAL_TABLE ++#ifndef SQLITE_OMIT_VIRTUALTABLE + else if( IsVirtual(pTable) ){ + sqlite3VtabClear(db, pTable); + } +@@ -116058,10 +121594,14 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ + } + 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 || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return; ++ if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return; + deleteTable(db, pTable); + } ++SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3 *db, void *pTable){ ++ sqlite3DeleteTable(db, (Table*)pTable); ++} + + + /* +@@ -116596,20 +122136,14 @@ SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){ + } + #endif + +-/* +-** Name of the special TEMP trigger used to implement RETURNING. The +-** name begins with "sqlite_" so that it is guaranteed not to collide +-** with any application-generated triggers. +-*/ +-#define RETURNING_TRIGGER_NAME "sqlite_returning" +- + /* + ** Clean up the data structures associated with the RETURNING clause. + */ +-static void sqlite3DeleteReturning(sqlite3 *db, Returning *pRet){ ++static void sqlite3DeleteReturning(sqlite3 *db, void *pArg){ ++ Returning *pRet = (Returning*)pArg; + Hash *pHash; + pHash = &(db->aDb[1].pSchema->trigHash); +- sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0); ++ sqlite3HashInsert(pHash, pRet->zName, 0); + sqlite3ExprListDelete(db, pRet->pReturnEL); + sqlite3DbFree(db, pRet); + } +@@ -116637,7 +122171,7 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ + if( pParse->pNewTrigger ){ + sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger"); + }else{ +- assert( pParse->bReturning==0 ); ++ assert( pParse->bReturning==0 || pParse->ifNotExists ); + } + pParse->bReturning = 1; + pRet = sqlite3DbMallocZero(db, sizeof(*pRet)); +@@ -116648,11 +122182,12 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ + pParse->u1.pReturning = pRet; + pRet->pParse = pParse; + pRet->pReturnEL = pList; +- sqlite3ParserAddCleanup(pParse, +- (void(*)(sqlite3*,void*))sqlite3DeleteReturning, pRet); ++ sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet); + testcase( pParse->earlyCleanup ); + if( db->mallocFailed ) return; +- pRet->retTrig.zName = RETURNING_TRIGGER_NAME; ++ 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; +@@ -116663,8 +122198,9 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){ + pRet->retTStep.pTrig = &pRet->retTrig; + pRet->retTStep.pExprList = pList; + pHash = &(db->aDb[1].pSchema->trigHash); +- assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr ); +- if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) ++ assert( sqlite3HashFind(pHash, pRet->zName)==0 ++ || pParse->nErr || pParse->ifNotExists ); ++ if( sqlite3HashInsert(pHash, pRet->zName, &pRet->retTrig) + ==&pRet->retTrig ){ + sqlite3OomFault(db); + } +@@ -116698,7 +122234,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){ + } + if( !IN_RENAME_OBJECT ) sqlite3DequoteToken(&sName); + +- /* Because keywords GENERATE ALWAYS can be converted into indentifiers ++ /* 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. */ +@@ -116845,7 +122381,8 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, Column *pCol){ + + assert( zIn!=0 ); + while( zIn[0] ){ +- h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; ++ u8 x = *(u8*)zIn; ++ h = (h<<8) + sqlite3UpperToLower[x]; + zIn++; + if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ + aff = SQLITE_AFF_TEXT; +@@ -116919,7 +122456,7 @@ 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 defaut value text */ ++ const char *zEnd /* First character past end of default value text */ + ){ + Table *p; + Column *pCol; +@@ -117191,6 +122728,14 @@ SQLITE_PRIVATE void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType + 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; +@@ -117259,7 +122804,7 @@ static int identLength(const char *z){ + ** 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 alpha-numeric ++** 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. +@@ -117327,7 +122872,8 @@ static char *createTableStmt(sqlite3 *db, Table *p){ + /* SQLITE_AFF_TEXT */ " TEXT", + /* SQLITE_AFF_NUMERIC */ " NUM", + /* SQLITE_AFF_INTEGER */ " INT", +- /* SQLITE_AFF_REAL */ " REAL" ++ /* SQLITE_AFF_REAL */ " REAL", ++ /* SQLITE_AFF_FLEXNUM */ " NUM", + }; + int len; + const char *zType; +@@ -117343,10 +122889,12 @@ static char *createTableStmt(sqlite3 *db, Table *p){ + 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) ); + memcpy(&zStmt[k], zType, len); + k += len; +@@ -117408,7 +122956,7 @@ static void estimateIndexWidth(Index *pIdx){ + for(i=0; i nColumn; i++){ + i16 x = pIdx->aiColumn[i]; + assert( x pTable->nCol ); +- wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst; ++ wIndex += x<0 ? 1 : aCol[x].szEst; + } + pIdx->szIdxRow = sqlite3LogEst(wIndex*4); + } +@@ -117463,7 +123011,8 @@ static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){ + /* 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. The ++** 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. + ** +@@ -117491,7 +123040,7 @@ static void recomputeColumnsNotIndexed(Index *pIdx){ + } + } + pIdx->colNotIdxed = ~m; +- assert( (pIdx->colNotIdxed>>63)==1 ); ++ assert( (pIdx->colNotIdxed>>63)==1 ); /* See note-20221022-a */ + } + + /* +@@ -117760,6 +123309,7 @@ SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ + ** 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; + } +@@ -118095,6 +123645,17 @@ SQLITE_PRIVATE void sqlite3EndTable( + /* 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, 1, 0, 0, ++ sqlite3MPrintf(db, "SELECT*FROM\"%w\".\"%w\"", ++ db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); ++ } ++ sqlite3VdbeAddOp4(v, OP_SqlExec, 1, 0, 0, ++ sqlite3MPrintf(db, "PRAGMA \"%w\".integrity_check(%Q)", ++ db->aDb[iDb].zDbSName, p->zName), P4_DYNAMIC); + } + + /* Add the table to the in-memory representation of the database. +@@ -118232,7 +123793,7 @@ create_view_fail: + ** the columns of the view in the pTable structure. Return the number + ** of errors. If an error is seen leave an error message in pParse->zErrMsg. + */ +-SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ ++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 */ +@@ -118257,9 +123818,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ + + #ifndef SQLITE_OMIT_VIEW + /* A positive nCol means the columns names for this view are +- ** already known. ++ ** already known. This routine is not called unless either the ++ ** table is virtual or nCol is zero. + */ +- if( pTable->nCol>0 ) return 0; ++ 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 +@@ -118325,8 +123887,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ + && pTable->nCol==pSel->pEList->nExpr + ){ + assert( db->mallocFailed==0 ); +- sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel, +- SQLITE_AFF_NONE); ++ sqlite3SubqueryColumnTypes(pParse, pTable, pSel, SQLITE_AFF_NONE); + } + }else{ + /* CREATE VIEW name AS... without an argument list. Construct +@@ -118355,6 +123916,11 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ + #endif /* SQLITE_OMIT_VIEW */ + return 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 +@@ -119139,7 +124705,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( + #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 initialising a database schema. ++ ** if initializing a database schema. + */ + if( !db->init.busy ){ + pTab = sqlite3SrcListLookup(pParse, pTblName); +@@ -119220,7 +124786,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( + } + if( !IN_RENAME_OBJECT ){ + if( !db->init.busy ){ +- if( sqlite3FindTable(db, zName, 0)!=0 ){ ++ if( sqlite3FindTable(db, zName, pDb->zDbSName)!=0 ){ + sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); + goto exit_create_index; + } +@@ -119373,6 +124939,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( + j = XN_EXPR; + pIndex->aiColumn[i] = XN_EXPR; + pIndex->uniqNotNull = 0; ++ pIndex->bHasExpr = 1; + }else{ + j = pCExpr->iColumn; + assert( j<=0x7fff ); +@@ -119384,6 +124951,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( + } + if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){ + pIndex->bHasVCol = 1; ++ pIndex->bHasExpr = 1; + } + } + pIndex->aiColumn[i] = (i16)j; +@@ -119873,12 +125441,13 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token * + */ + SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ + int i; ++ assert( db!=0 ); + if( pList==0 ) return; + assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */ + for(i=0; i nId; i++){ + sqlite3DbFree(db, pList->a[i].zName); + } +- sqlite3DbFreeNN(db, pList); ++ sqlite3DbNNFreeNN(db, pList); + } + + /* +@@ -120081,11 +125650,12 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ + 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; i nSrc; i++, pItem++){ +- if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase); +- sqlite3DbFree(db, pItem->zName); +- if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias); ++ if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase); ++ if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName); ++ if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias); + if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy); + if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg); + sqlite3DeleteTable(db, pItem->pTab); +@@ -120096,7 +125666,7 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ + sqlite3ExprDelete(db, pItem->u3.pOn); + } + } +- sqlite3DbFreeNN(db, pList); ++ sqlite3DbNNFreeNN(db, pList); + } + + /* +@@ -120677,7 +126247,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ + if( iDb<0 ) return; + z = sqlite3NameFromToken(db, pObjName); + if( z==0 ) return; +- zDb = db->aDb[iDb].zDbSName; ++ zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; + pTab = sqlite3FindTable(db, z, zDb); + if( pTab ){ + reindexTable(pParse, pTab, 0); +@@ -120687,6 +126257,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ + 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; +@@ -120792,7 +126363,7 @@ SQLITE_PRIVATE void sqlite3CteDelete(sqlite3 *db, Cte *pCte){ + + /* + ** This routine is invoked once per CTE by the parser while parsing a +-** WITH clause. The CTE described by teh third argument is added to ++** 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. + */ +@@ -120852,6 +126423,9 @@ SQLITE_PRIVATE void sqlite3WithDelete(sqlite3 *db, With *pWith){ + sqlite3DbFree(db, pWith); + } + } ++SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3 *db, void *pWith){ ++ sqlite3WithDelete(db, (With*)pWith); ++} + #endif /* !defined(SQLITE_OMIT_CTE) */ + + /************** End of build.c ***********************************************/ +@@ -121043,6 +126617,7 @@ SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){ + ** strings is BINARY. + */ + db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0); ++ sqlite3ExpirePreparedStatements(db, 1); + } + + /* +@@ -121348,19 +126923,21 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ + 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(0, (Trigger*)sqliteHashData(pElem)); ++ sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem)); + } + sqlite3HashClear(&temp2); + sqlite3HashInit(&pSchema->tblHash); + for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ + Table *pTab = sqliteHashData(pElem); +- sqlite3DeleteTable(0, pTab); ++ sqlite3DeleteTable(&xdb, pTab); + } + sqlite3HashClear(&temp1); + sqlite3HashClear(&pSchema->fkeyHash); +@@ -121431,8 +127008,9 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ + Table *pTab; + assert( pItem && pSrc->nSrc>=1 ); + pTab = sqlite3LocateTableItem(pParse, 0, pItem); +- sqlite3DeleteTable(pParse->db, pItem->pTab); ++ if( pItem->pTab ) sqlite3DeleteTable(pParse->db, pItem->pTab); + pItem->pTab = pTab; ++ pItem->fg.notCte = 1; + if( pTab ){ + pTab->nTabRef++; + if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){ +@@ -121459,18 +127037,42 @@ SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char * + ** 1) It is a virtual table and no implementation of the xUpdate method + ** has been provided + ** +-** 2) It is a system table (i.e. sqlite_schema), this call is not ++** 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 + ** +-** 3) The table is a shadow table, the database connection is in ++** 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){ ++ 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 sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0; ++ return vtabIsReadOnly(pParse, pTab); + } + if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; + db = pParse->db; +@@ -121482,17 +127084,21 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){ + } + + /* +-** Check to make sure the given table is writable. If it is not +-** writable, generate an error message and return 1. If it is +-** writable return 0; ++** 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, int viewOk){ ++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( !viewOk && IsView(pTab) ){ ++ if( IsView(pTab) ++ && (pTrigger==0 || (pTrigger->bReturning && pTrigger->pNext==0)) ++ ){ + sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); + return 1; + } +@@ -121557,7 +127163,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( + sqlite3 *db = pParse->db; + Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */ + Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ +- ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ ++ 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; +@@ -121595,14 +127201,20 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( + ); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); ++ assert( pPk!=0 ); ++ assert( pPk->nKeyCol>=1 ); + if( pPk->nKeyCol==1 ){ +- const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName; ++ 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; i nKeyCol; i++){ +- Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName); ++ 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); +@@ -121631,7 +127243,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere( + pOrderBy,0,pLimit + ); + +- /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ ++ /* 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; +@@ -121746,7 +127358,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( + goto delete_from_cleanup; + } + +- if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ ++ if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ + goto delete_from_cleanup; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); +@@ -121845,21 +127457,22 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->pSchema==pTab->pSchema ); +- sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); + if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ +- sqlite3VdbeChangeP3(v, -1, memCnt ? memCnt : -1); ++ 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_VarSelect ) bComplex = 1; ++ 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; +- nPk = 1; ++ assert( nPk==1 ); + iRowSet = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); + }else{ +@@ -121887,7 +127500,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( + 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 ); ++ 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); +@@ -122047,7 +127661,7 @@ delete_from_cleanup: + sqlite3ExprListDelete(db, pOrderBy); + sqlite3ExprDelete(db, pLimit); + #endif +- sqlite3DbFree(db, aToOpen); ++ if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen); + return; + } + /* Make sure "isView" and other macros defined above are undefined. Otherwise +@@ -122224,9 +127838,11 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete( + sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); + + /* Invoke AFTER DELETE trigger programs. */ +- sqlite3CodeRowTrigger(pParse, pTrigger, +- TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel +- ); ++ 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 +@@ -122539,6 +128155,42 @@ static void lengthFunc( + } + } + ++/* ++** 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. + ** +@@ -122815,7 +128467,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + }else if( n==0 ){ + r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); + }else{ +- zBuf = sqlite3_mprintf("%.*f",n,r); ++ zBuf = sqlite3_mprintf("%!.*f",n,r); + if( zBuf==0 ){ + sqlite3_result_error_nomem(context); + return; +@@ -123015,7 +128667,7 @@ struct compareInfo { + + /* + ** For LIKE and GLOB matching on EBCDIC machines, assume that every +-** character is exactly one byte in size. Also, provde the Utf8Read() ++** character is exactly one byte in size. Also, provide the Utf8Read() + ** macro for fast reading of the next character in the common case where + ** the next character is ASCII. + */ +@@ -123130,7 +128782,7 @@ static int patternCompare( + ** c but in the other case and search the input string for either + ** c or cx. + */ +- if( c<=0x80 ){ ++ if( c<0x80 ){ + char zStop[3]; + int bMatch; + if( noCase ){ +@@ -123213,7 +128865,13 @@ static int patternCompare( + ** non-zero if there is no match. + */ + SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ +- return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); ++ if( zString==0 ){ ++ return zGlobPattern!=0; ++ }else if( zGlobPattern==0 ){ ++ return 1; ++ }else { ++ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); ++ } + } + + /* +@@ -123221,7 +128879,13 @@ SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ + ** a miss - like strcmp(). + */ + SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ +- return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); ++ if( zStr==0 ){ ++ return zPattern!=0; ++ }else if( zPattern==0 ){ ++ return 1; ++ }else{ ++ return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); ++ } + } + + /* +@@ -123236,7 +128900,7 @@ SQLITE_API int sqlite3_like_count = 0; + + /* + ** Implementation of the like() SQL function. This function implements +-** the build-in LIKE operator. The first argument to the function is the ++** 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 +@@ -123460,7 +129124,7 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ + } + case SQLITE_BLOB: { + char const *zBlob = sqlite3_value_blob(pValue); +- int nBlob = sqlite3_value_bytes(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 ){ +@@ -123569,6 +129233,7 @@ static void charFunc( + *zOut++ = 0x80 + (u8)(c & 0x3F); + } \ + } ++ *zOut = 0; + sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8); + } + +@@ -123597,10 +129262,101 @@ static void hexFunc( + *(z++) = hexdigits[c&0xf]; + } + *z = 0; +- sqlite3_result_text(context, zHex, n*2, sqlite3_free); ++ 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( z 0 ){ ++ const char *v = (const char*)sqlite3_value_text(argv[i]); ++ if( v!=0 ){ ++ if( j>0 && 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_FUNCTION compile-time option is used. ++** 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 +@@ -123818,6 +129649,9 @@ static void unknownFunc( + sqlite3_value **argv + ){ + /* no-op */ ++ (void)context; ++ (void)argc; ++ (void)argv; + } + #endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/ + +@@ -123919,13 +129753,68 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ + */ + typedef struct SumCtx SumCtx; + struct SumCtx { +- double rSum; /* Floating point sum */ +- i64 iSum; /* Integer sum */ ++ 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 overflow; /* True if integer overflow seen */ +- u8 approx; /* True if non-integer value was input to the sum */ ++ 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. + ** +@@ -123945,15 +129834,29 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + type = sqlite3_value_numeric_type(argv[0]); + if( p && type!=SQLITE_NULL ){ + p->cnt++; +- if( type==SQLITE_INTEGER ){ +- i64 v = sqlite3_value_int64(argv[0]); +- p->rSum += v; +- if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ +- p->approx = p->overflow = 1; ++ 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{ +- p->rSum += sqlite3_value_double(argv[0]); +- p->approx = 1; ++ if( type==SQLITE_INTEGER ){ ++ kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0])); ++ }else{ ++ p->ovrfl = 0; ++ kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0])); ++ } + } + } + } +@@ -123970,13 +129873,18 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){ + if( ALWAYS(p) && type!=SQLITE_NULL ){ + assert( p->cnt>0 ); + p->cnt--; +- assert( type==SQLITE_INTEGER || p->approx ); +- if( type==SQLITE_INTEGER && p->approx==0 ){ +- i64 v = sqlite3_value_int64(argv[0]); +- p->rSum -= v; +- p->iSum -= v; ++ if( !p->approx ){ ++ p->iSum -= sqlite3_value_int64(argv[0]); ++ }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{ +- p->rSum -= sqlite3_value_double(argv[0]); ++ kahanBabuskaNeumaierStep(p, -sqlite3_value_double(argv[0])); + } + } + } +@@ -123987,10 +129895,14 @@ static void sumFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ +- if( p->overflow ){ +- sqlite3_result_error(context,"integer overflow",-1); +- }else if( p->approx ){ +- sqlite3_result_double(context, p->rSum); ++ if( p->approx ){ ++ if( p->ovrfl ){ ++ sqlite3_result_error(context,"integer overflow",-1); ++ }else if( !sqlite3IsNaN(p->rErr) ){ ++ sqlite3_result_double(context, p->rSum+p->rErr); ++ }else{ ++ sqlite3_result_double(context, p->rSum); ++ } + }else{ + sqlite3_result_int64(context, p->iSum); + } +@@ -124000,14 +129912,29 @@ static void avgFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ +- sqlite3_result_double(context, p->rSum/(double)p->cnt); ++ double r; ++ if( p->approx ){ ++ r = p->rSum; ++ if( !sqlite3IsNaN(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); +- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ +- sqlite3_result_double(context, p ? p->rSum : (double)0); ++ if( p ){ ++ if( p->approx ){ ++ r = p->rSum; ++ if( !sqlite3IsNaN(p->rErr) ) r += p->rErr; ++ }else{ ++ r = (double)(p->iSum); ++ } ++ } ++ sqlite3_result_double(context, r); + } + + /* +@@ -124126,6 +130053,7 @@ static void minMaxFinalize(sqlite3_context *context){ + + /* + ** group_concat(EXPR, ?SEPARATOR?) ++** string_agg(EXPR, SEPARATOR) + ** + ** The SEPARATOR goes before the EXPR string. This is tragic. The + ** groupConcatInverse() implementation would have been easier if the +@@ -124229,7 +130157,7 @@ static void groupConcatInverse( + 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 frist to initialize it */ ++ ** run first to initialize it */ + if( ALWAYS(pGCC) ){ + int nVS; + /* Must call sqlite3_value_text() to convert the argument into text prior +@@ -124313,8 +130241,10 @@ SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){ + ** 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; +@@ -124322,10 +130252,13 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) + pInfo = (struct compareInfo*)&likeInfoNorm; + flags = SQLITE_FUNC_LIKE; + } +- sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); +- sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0); +- sqlite3FindFunction(db, "like", 2, SQLITE_UTF8, 0)->funcFlags |= flags; +- sqlite3FindFunction(db, "like", 3, SQLITE_UTF8, 0)->funcFlags |= flags; ++ 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; ++ } + } + + /* +@@ -124446,6 +130379,18 @@ static void ceilingFunc( + 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: + ** +@@ -124484,17 +130429,15 @@ static void logFunc( + } + ans = log(x)/b; + }else{ +- ans = log(x); + switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){ + case 1: +- /* Convert from natural logarithm to log base 10 */ +- ans /= M_LN10; ++ ans = log10(x); + break; + case 2: +- /* Convert from natural logarithm to log base 2 */ +- ans /= M_LN2; ++ ans = log2(x); + break; + default: ++ ans = log(x); + break; + } + } +@@ -124563,6 +130506,7 @@ static void piFunc( + sqlite3_value **argv + ){ + assert( argc==0 ); ++ (void)argv; + sqlite3_result_double(context, M_PI); + } + +@@ -124586,6 +130530,37 @@ static void signFunc( + 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. ++*/ ++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]); ++ 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 */ ++ + /* + ** All of the FuncDef structures in the aBuiltinFunc[] array above + ** to the global function hash table. This occurs at start-time (as +@@ -124650,12 +130625,16 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ + FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), ++ FUNCTION2(octet_length, 1, 0, 0, bytelengthFunc,SQLITE_FUNC_BYTELEN), + FUNCTION(instr, 2, 0, 0, instrFunc ), + FUNCTION(printf, -1, 0, 0, printfFunc ), + FUNCTION(format, -1, 0, 0, printfFunc ), + FUNCTION(unicode, 1, 0, 0, unicodeFunc ), + FUNCTION(char, -1, 0, 0, charFunc ), + FUNCTION(abs, 1, 0, 0, absFunc ), ++#ifdef SQLITE_DEBUG ++ FUNCTION(fpdecode, 3, 0, 0, fpdecodeFunc ), ++#endif + #ifndef SQLITE_OMIT_FLOATING_POINT + FUNCTION(round, 1, 0, 0, roundFunc ), + FUNCTION(round, 2, 0, 0, roundFunc ), +@@ -124663,6 +130642,13 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ + FUNCTION(upper, 1, 0, 0, upperFunc ), + FUNCTION(lower, 1, 0, 0, lowerFunc ), + FUNCTION(hex, 1, 0, 0, hexFunc ), ++ FUNCTION(unhex, 1, 0, 0, unhexFunc ), ++ FUNCTION(unhex, 2, 0, 0, unhexFunc ), ++ FUNCTION(concat, -1, 0, 0, concatFunc ), ++ FUNCTION(concat, 0, 0, 0, 0 ), ++ FUNCTION(concat_ws, -1, 0, 0, concatwsFunc ), ++ FUNCTION(concat_ws, 0, 0, 0, 0 ), ++ FUNCTION(concat_ws, 1, 0, 0, 0 ), + INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ), + VFUNCTION(random, 0, 0, 0, randomFunc ), + VFUNCTION(randomblob, 1, 0, 0, randomBlob ), +@@ -124692,6 +130678,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ + groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), + WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep, + groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), ++ WAGGREGATE(string_agg, 2, 0, 0, groupConcatStep, ++ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0), + + LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE), + #ifdef SQLITE_CASE_SENSITIVE_LIKE +@@ -125634,6 +131622,7 @@ static int isSetNullAction(Parse *pParse, FKey *pFKey){ + 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; + } + } +@@ -125828,6 +131817,8 @@ SQLITE_PRIVATE void sqlite3FkCheck( + } + 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 +@@ -125943,7 +131934,11 @@ SQLITE_PRIVATE int sqlite3FkRequired( + /* Check if any parent key columns are being modified. */ + for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ + if( fkParentIsModified(pTab, p, aChange, chngRowid) ){ +- if( p->aAction[1]!=OE_None ) return 2; ++ if( (pParse->db->flags & SQLITE_FkNoAction)==0 ++ && p->aAction[1]!=OE_None ++ ){ ++ return 2; ++ } + bHaveFK = 1; + } + } +@@ -125993,6 +131988,7 @@ static Trigger *fkActionTrigger( + 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; + } +@@ -126093,22 +132089,22 @@ static Trigger *fkActionTrigger( + + if( action==OE_Restrict ){ + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); +- Token tFrom; +- Token tDb; ++ SrcList *pSrc; + Expr *pRaise; + +- tFrom.z = zFrom; +- tFrom.n = nFrom; +- tDb.z = db->aDb[iDb].zDbSName; +- tDb.n = sqlite3Strlen30(tDb.z); +- + pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); + 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); ++ pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); ++ } + pSelect = sqlite3SelectNew(pParse, + sqlite3ExprListAppend(pParse, 0, pRaise), +- sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom), ++ pSrc, + pWhere, + 0, 0, 0, 0, 0 + ); +@@ -126215,17 +132211,17 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){ + 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 || db->pnBytesFreed==0 ){ ++ if( db->pnBytesFreed==0 ){ + if( pFKey->pPrevTo ){ + pFKey->pPrevTo->pNextTo = pFKey->pNextTo; + }else{ +- void *p = (void *)pFKey->pNextTo; +- const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo); +- sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, p); ++ 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; +@@ -126288,8 +132284,10 @@ SQLITE_PRIVATE void sqlite3OpenTable( + assert( pParse->pVdbe!=0 ); + v = pParse->pVdbe; + assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); +- sqlite3TableLock(pParse, iDb, pTab->tnum, +- (opcode==OP_OpenWrite)?1:0, pTab->zName); ++ 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)); +@@ -126323,43 +132321,68 @@ SQLITE_PRIVATE void sqlite3OpenTable( + ** is managed along with the rest of the Index structure. It will be + ** released when sqlite3DeleteIndex() is called. + */ +-SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ ++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 ){ +- /* 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; ++ sqlite3OomFault(db); ++ return 0; ++ } ++ for(n=0; n nColumn; 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); + } +- for(n=0; n nColumn; 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->aColExpr!=0 ); +- aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); ++ if( aff SQLITE_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; i nCol; i++){ ++ if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ ++ zColAff[j++] = pTab->aCol[i].affinity; + } +- if( aff SQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC; +- pIdx->zColAff[n] = aff; + } +- pIdx->zColAff[n] = 0; ++ do{ ++ zColAff[j--] = 0; ++ }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB ); + } +- +- return pIdx->zColAff; ++ return zColAff; + } + + /* +@@ -126393,7 +132416,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ + ** For STRICT tables: + ** ------------------ + ** +-** Generate an appropropriate OP_TypeCheck opcode that will verify the ++** 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 +@@ -126403,7 +132426,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ + ** Apply the type checking to that array of registers. + */ + SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ +- int i, j; ++ int i; + char *zColAff; + if( pTab->tabFlags & TF_Strict ){ + if( iReg==0 ){ +@@ -126412,7 +132435,7 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ + ** OP_MakeRecord is found */ + VdbeOp *pPrev; + sqlite3VdbeAppendP4(v, pTab, P4_TABLE); +- pPrev = sqlite3VdbeGetOp(v, -1); ++ pPrev = sqlite3VdbeGetLastOp(v); + assert( pPrev!=0 ); + assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); + pPrev->opcode = OP_TypeCheck; +@@ -126426,22 +132449,11 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ + } + zColAff = pTab->zColAff; + if( zColAff==0 ){ +- sqlite3 *db = sqlite3VdbeDb(v); +- zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1); ++ zColAff = sqlite3TableAffinityStr(0, pTab); + if( !zColAff ){ +- sqlite3OomFault(db); ++ sqlite3OomFault(sqlite3VdbeDb(v)); + return; + } +- +- for(i=j=0; i nCol; i++){ +- assert( pTab->aCol[i].affinity!=0 || sqlite3VdbeParser(v)->nErr>0 ); +- 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 ); + pTab->zColAff = zColAff; + } + assert( zColAff!=0 ); +@@ -126450,7 +132462,7 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ + if( iReg ){ + sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); + }else{ +- assert( sqlite3VdbeGetOp(v, -1)->opcode==OP_MakeRecord ++ assert( sqlite3VdbeGetLastOp(v)->opcode==OP_MakeRecord + || sqlite3VdbeDb(v)->mallocFailed ); + sqlite3VdbeChangeP4(v, -1, zColAff, i); + } +@@ -126536,7 +132548,7 @@ SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns( + */ + sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore); + if( (pTab->tabFlags & TF_HasStored)!=0 ){ +- pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1); ++ 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 +@@ -127035,7 +133047,7 @@ SQLITE_PRIVATE void sqlite3Insert( + + /* Cannot insert into a read-only table. + */ +- if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ ++ if( sqlite3IsReadOnly(pParse, pTab, pTrigger) ){ + goto insert_cleanup; + } + +@@ -127442,7 +133454,12 @@ SQLITE_PRIVATE void sqlite3Insert( + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore); + } + }else{ +- sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore); ++ 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); ++ } + } + } + +@@ -127477,7 +133494,7 @@ SQLITE_PRIVATE void sqlite3Insert( + } + + /* Copy the new data already generated. */ +- assert( pTab->nNVCol>0 ); ++ assert( pTab->nNVCol>0 || pParse->nErr>0 ); + sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1); + + #ifndef SQLITE_OMIT_GENERATED_COLUMNS +@@ -127579,7 +133596,9 @@ SQLITE_PRIVATE void sqlite3Insert( + sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, + regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert + ); +- sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); ++ 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 +@@ -127663,7 +133682,7 @@ insert_cleanup: + sqlite3UpsertDelete(db, pUpsert); + sqlite3SelectDelete(db, pSelect); + sqlite3IdListDelete(db, pColumn); +- sqlite3DbFree(db, aRegIdx); ++ if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx); + } + + /* Make sure "isView" and other macros defined above are undefined. Otherwise +@@ -127689,7 +133708,7 @@ insert_cleanup: + /* 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 modifed by an UPDATE statement. ++** columns that are being modified by an UPDATE statement. + */ + static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_COLUMN ){ +@@ -127912,7 +133931,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( + int *aiChng, /* column i is unchanged if aiChng[i]<0 */ + Upsert *pUpsert /* ON CONFLICT clauses, if any. NULL otherwise */ + ){ +- Vdbe *v; /* VDBE under constrution */ ++ 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 */ +@@ -128027,6 +134046,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( + 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); +@@ -128394,7 +134414,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( + pIdx; + pIdx = indexIteratorNext(&sIdxIter, &ix) + ){ +- int regIdx; /* Range of registers hold conent for pIdx */ ++ 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 */ +@@ -128889,6 +134909,8 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( + + 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 +@@ -128901,18 +134923,18 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices( + assert( v!=0 ); + if( iBase<0 ) iBase = pParse->nTab; + iDataCur = iBase++; +- if( piDataCur ) *piDataCur = iDataCur; ++ *piDataCur = iDataCur; + if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){ + sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op); +- }else{ ++ }else if( pParse->db->noSharedCache==0 ){ + sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName); + } +- if( piIdxCur ) *piIdxCur = iBase; ++ *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) ){ +- if( piDataCur ) *piDataCur = iIdxCur; ++ *piDataCur = iIdxCur; + p5 = 0; + } + if( aToOpen==0 || aToOpen[i+1] ){ +@@ -129210,7 +135232,7 @@ static int xferOptimization( + } + #endif + #ifndef SQLITE_OMIT_FOREIGN_KEY +- /* Disallow the transfer optimization if the destination table constains ++ /* 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 +@@ -129890,9 +135912,9 @@ struct sqlite3_api_routines { + const char *(*filename_journal)(const char*); + const char *(*filename_wal)(const char*); + /* Version 3.32.0 and later */ +- char *(*create_filename)(const char*,const char*,const char*, ++ const char *(*create_filename)(const char*,const char*,const char*, + int,const char**); +- void (*free_filename)(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*); +@@ -129916,6 +135938,15 @@ struct sqlite3_api_routines { + 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*)); + }; + + /* +@@ -130240,6 +136271,15 @@ typedef int (*sqlite3_loadext_entry)( + #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 + #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + + #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) +@@ -130752,7 +136792,16 @@ static const sqlite3_api_routines sqlite3Apis = { + 0, + 0, + #endif +- sqlite3_db_name ++ 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 + }; + + /* True if x is the directory separator character +@@ -130825,15 +136874,25 @@ static int sqlite3LoadExtension( + /* 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 */ ++ ** 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 mutex); + if( onoff ){ + db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc; +@@ -131007,6 +137069,9 @@ 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 ){ +@@ -131059,6 +137124,9 @@ SQLITE_API int sqlite3_cancel_auto_extension( + int i; + int n = 0; + wsdAutoextInit; ++#ifdef SQLITE_ENABLE_API_ARMOR ++ if( xInit==0 ) return 0; ++#endif + sqlite3_mutex_enter(mutex); + for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ + if( wsdAutoext.aExt[i]==xInit ){ +@@ -132252,7 +138320,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + aFcntl[2] = zRight; + aFcntl[3] = 0; + db->busyHandler.nBusy = 0; +- rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); ++ rc = sqlite3mcFileControlPragma(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); + if( rc==SQLITE_OK ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT); +@@ -132658,7 +138726,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + ** + ** The first form reports the current local setting for the + ** page cache spill size. The second form turns cache spill on +- ** or off. When turnning cache spill on, the size is set to the ++ ** 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 +@@ -132928,7 +138996,11 @@ SQLITE_PRIVATE void sqlite3Pragma( + #endif + + if( sqlite3GetBoolean(zRight, 0) ){ +- db->flags |= mask; ++ if( (mask & SQLITE_WriteSchema)==0 ++ || (db->flags & SQLITE_Defensive)==0 ++ ){ ++ db->flags |= mask; ++ } + }else{ + db->flags &= ~mask; + if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; +@@ -133328,7 +139400,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + zDb = db->aDb[iDb].zDbSName; + sqlite3CodeVerifySchema(pParse, iDb); + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); +- if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; ++ sqlite3TouchRegister(pParse, pTab->nCol+regRow); + sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); + sqlite3VdbeLoadString(v, regResult, pTab->zName); + assert( IsOrdinaryTable(pTab) ); +@@ -133369,7 +139441,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + ** regRow..regRow+n. If any of the child key values are NULL, this + ** row cannot cause an FK violation. Jump directly to addrOk in + ** this case. */ +- if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol; ++ sqlite3TouchRegister(pParse, regRow + pFK->nCol); + for(j=0; j nCol; j++){ + int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom; + sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j); +@@ -133436,9 +139508,9 @@ SQLITE_PRIVATE void sqlite3Pragma( + ** 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 wherease integrity_check is O(NlogN). ++ ** is linear time whereas integrity_check is O(NlogN). + ** +- ** The maximum nubmer of errors is 100 by default. A different default ++ ** 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 +@@ -133498,6 +139570,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + if( iDb>=0 && i!=iDb ) continue; + + sqlite3CodeVerifySchema(pParse, i); ++ pParse->okConstFactor = 0; /* tag-20230327-1 */ + + /* Do an integrity check of the B-Tree + ** +@@ -133533,7 +139606,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + aRoot[0] = cnt; + + /* Make sure sufficient number of registers have been allocated */ +- pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); ++ sqlite3TouchRegister(pParse, 8+mxIdx); + sqlite3ClearTempRegCache(pParse); + + /* Do the b-tree integrity checks */ +@@ -133552,15 +139625,48 @@ SQLITE_PRIVATE void sqlite3Pragma( + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx, *pPk; +- Index *pPrior = 0; ++ Index *pPrior = 0; /* Previous index */ + int loopTop; + int iDataCur, iIdxCur; + int r1 = -1; +- int bStrict; ++ int bStrict; /* True for a STRICT table */ ++ int r2; /* Previous key for WITHOUT ROWID tables */ ++ int mxCol; /* Maximum non-virtual column number */ + +- if( !IsOrdinaryTable(pTab) ) continue; + if( pObjTab && pObjTab!=pTab ) continue; +- pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); ++ if( !IsOrdinaryTable(pTab) ){ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ sqlite3_vtab *pVTab; ++ int a1; ++ 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); ++#endif ++ 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. +@@ -133574,52 +139680,180 @@ SQLITE_PRIVATE void sqlite3Pragma( + 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; j nCol; 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 ){ +- /* Sanity check on record header decoding */ +- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3); +- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); +- VdbeComment((v, "(right-most column)")); ++ 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; j nKeyCol; j++){ ++ sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j); ++ } ++ } + } +- /* Verify that all NOT NULL columns really are NOT NULL. At the +- ** same time verify the type of the content of STRICT tables */ ++ /* 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; j nCol; j++){ + char *zErr; +- Column *pCol = pTab->aCol + j; +- int doError, jmp2; ++ 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( pCol->notNull==0 && !bStrict ) continue; +- doError = bStrict ? sqlite3VdbeMakeLabel(pParse) : 0; +- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); +- if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){ +- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); ++ 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 ){ +- jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); ++ /* (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); ++ 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( bStrict && pCol->eCType!=COLTYPE_ANY ){ +- sqlite3VdbeGoto(v, doError); ++ if( doTypeCheck ){ ++ sqlite3VdbeGoto(v, labelError); ++ sqlite3VdbeJumpHere(v, jmp2); ++ sqlite3VdbeJumpHere(v, jmp3); + }else{ +- integrityCheckResultRow(v); ++ /* VDBE byte code will fall thru */ + } +- sqlite3VdbeJumpHere(v, jmp2); + } +- if( (pTab->tabFlags & TF_Strict)!=0 +- && pCol->eCType!=COLTYPE_ANY +- ){ +- jmp2 = sqlite3VdbeAddOp3(v, OP_IsNullOrType, 3, 0, +- sqlite3StdTypeMap[pCol->eCType-1]); ++ 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); +- sqlite3VdbeResolveLabel(v, doError); +- integrityCheckResultRow(v); +- sqlite3VdbeJumpHere(v, jmp2); ++ }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 ){ +@@ -133648,7 +139882,8 @@ SQLITE_PRIVATE void sqlite3Pragma( + 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; ++ int jmp2, jmp3, jmp4, jmp5, label6; ++ int kk; + int ckUniq = sqlite3VdbeMakeLabel(pParse); + if( pPk==pIdx ) continue; + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, +@@ -133666,13 +139901,49 @@ SQLITE_PRIVATE void sqlite3Pragma( + 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; kk nKeyCol; 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; +- int kk; + for(kk=0; kk nKeyCol; kk++){ + int iCol = pIdx->aiColumn[kk]; + assert( iCol!=XN_ROWID && iCol nCol ); +@@ -133707,6 +139978,9 @@ SQLITE_PRIVATE void sqlite3Pragma( + integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, addr); + } ++ if( pPk ){ ++ sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol); ++ } + } + } + } +@@ -133857,6 +140131,11 @@ SQLITE_PRIVATE void sqlite3Pragma( + 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[] = { +@@ -134013,7 +140292,7 @@ SQLITE_PRIVATE void sqlite3Pragma( + 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 is needd */ ++ LogEst szThreshold; /* Size threshold above which reanalysis needed */ + char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ + u32 opMask; /* Mask of operations to perform */ + +@@ -134505,7 +140784,8 @@ static const sqlite3_module pragmaVtabModule = { + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ +- 0 /* xShadowName */ ++ 0, /* xShadowName */ ++ 0 /* xIntegrity */ + }; + + /* +@@ -134837,7 +141117,14 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl + #else + encoding = SQLITE_UTF8; + #endif +- sqlite3SetTextEncoding(db, encoding); ++ if( db->nVdbeActive>0 && encoding!=ENC(db) ++ && (db->mDbFlags & DBFLAG_Vacuum)==0 ++ ){ ++ rc = SQLITE_LOCKED; ++ goto initone_error_out; ++ }else{ ++ sqlite3SetTextEncoding(db, encoding); ++ } + }else{ + /* If opening an attached database, the encoding much match ENC(db) */ + if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){ +@@ -135051,8 +141338,8 @@ static void schemaIsValid(Parse *pParse){ + 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); +- pParse->rc = SQLITE_SCHEMA; + } + + /* Close the transaction, if one was opened. */ +@@ -135105,15 +141392,15 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ + assert( db->pParse==pParse ); + assert( pParse->nested==0 ); + #ifndef SQLITE_OMIT_SHARED_CACHE +- sqlite3DbFree(db, pParse->aTableLock); ++ if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock); + #endif + while( pParse->pCleanup ){ + ParseCleanup *pCleanup = pParse->pCleanup; + pParse->pCleanup = pCleanup->pNext; + pCleanup->xCleanup(db, pCleanup->pPtr); +- sqlite3DbFreeNN(db, pCleanup); ++ sqlite3DbNNFreeNN(db, pCleanup); + } +- sqlite3DbFree(db, pParse->aLabel); ++ if( pParse->aLabel ) sqlite3DbNNFreeNN(db, pParse->aLabel); + if( pParse->pConstExpr ){ + sqlite3ExprListDelete(db, pParse->pConstExpr); + } +@@ -135122,8 +141409,6 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ + db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; + assert( pParse->db->pParse==pParse ); + db->pParse = pParse->pOuterParse; +- pParse->db = 0; +- pParse->disableLookaside = 0; + } + + /* +@@ -135132,7 +141417,7 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ + ** immediately. + ** + ** Use this mechanism for uncommon cleanups. There is a higher setup +-** cost for this mechansim (an extra malloc), so it should not be used ++** 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. +@@ -135224,9 +141509,18 @@ static int sqlite3Prepare( + sParse.pOuterParse = db->pParse; + db->pParse = &sParse; + sParse.db = db; +- sParse.pReprepare = pReprepare; ++ 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"); ++ 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 +@@ -135236,7 +141530,7 @@ static int sqlite3Prepare( + sParse.disableLookaside++; + DisableLookaside; + } +- sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0; ++ 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 +@@ -135277,7 +141571,9 @@ static int sqlite3Prepare( + } + } + +- sqlite3VtabUnlockList(db); ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( db->pDisconnect ) sqlite3VtabUnlockList(db); ++#endif + + if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ + char *zSqlCopy; +@@ -135383,6 +141679,7 @@ static int sqlite3LockAndPrepare( + assert( (rc&db->errMask)==rc ); + db->busyHandler.nBusy = 0; + sqlite3_mutex_leave(db->mutex); ++ assert( rc==SQLITE_OK || (*ppStmt)==0 ); + return rc; + } + +@@ -135661,6 +141958,10 @@ struct SortCtx { + } 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 */ + +@@ -135672,6 +141973,7 @@ struct SortCtx { + ** 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); +@@ -135691,7 +141993,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ + sqlite3WindowUnlinkFromSelect(p->pWin); + } + #endif +- if( bFree ) sqlite3DbFreeNN(db, p); ++ if( bFree ) sqlite3DbNNFreeNN(db, p); + p = pPrior; + bFree = 1; + } +@@ -135775,6 +142077,9 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( + 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. +@@ -135823,7 +142128,7 @@ static Select *findRightmost(Select *p){ + ** NATURAL FULL OUTER JT_NATRUAL|JT_LEFT|JT_RIGHT + ** + ** To preserve historical compatibly, SQLite also accepts a variety +-** of other non-standard and in many cases non-sensical join types. ++** 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: +@@ -136045,6 +142350,7 @@ static void unsetJoinExpr(Expr *p, int iTable, int nullable){ + } + if( p->op==TK_FUNCTION ){ + assert( ExprUseXList(p) ); ++ assert( p->pLeft==0 ); + if( p->x.pList ){ + int i; + for(i=0; i x.pList->nExpr; i++){ +@@ -136094,7 +142400,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ + if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; + joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON; + +- /* If this is a NATURAL join, synthesize an approprate USING clause ++ /* If this is a NATURAL join, synthesize an appropriate USING clause + ** to specify which columns should be joined. + */ + if( pRight->fg.jointype & JT_NATURAL ){ +@@ -136308,14 +142614,18 @@ static void pushOntoSorter( + ** (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_REFERENCE optimization, or due to the ++ ** the SQLITE_ENABLE_SORTER_REFERENCES optimization, or due to the + ** SQLITE_ECEL_OMITREF optimization, or due to the +- ** SortCtx.pDeferredRowLoad optimiation. In any of these cases ++ ** 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; +@@ -136362,7 +142672,7 @@ static void pushOntoSorter( + 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 sqltie3VdbeAddOp3() */ ++ 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); +@@ -136416,6 +142726,9 @@ static void pushOntoSorter( + sqlite3VdbeChangeP2(v, iSkip, + pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v)); + } ++#ifdef SQLITE_ENABLE_STMT_SCANSTATUS ++ pSort->addrPushEnd = sqlite3VdbeCurrentAddr(v)-1; ++#endif + } + + /* +@@ -136453,7 +142766,7 @@ static void codeOffset( + ** The returned value in this case is a copy of parameter iTab. + ** + ** WHERE_DISTINCT_ORDERED: +-** In this case rows are being delivered sorted order. The ephermal ++** 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, +@@ -136882,6 +143195,16 @@ static void selectInnerLoop( + 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 +@@ -137097,9 +143420,10 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ + */ + SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){ + if( p ){ ++ assert( p->db!=0 ); + assert( p->nRef>0 ); + p->nRef--; +- if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p); ++ if( p->nRef==0 ) sqlite3DbNNFreeNN(p->db, p); + } + } + +@@ -137238,6 +143562,16 @@ static void generateSortTail( + 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 ++ ++ ExplainQueryPlan2(addrExplain, (pParse, 0, ++ "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"") ++ ); ++ sqlite3VdbeScanStatusRange(v, addrExplain,pSort->addrPush,pSort->addrPushEnd); ++ sqlite3VdbeScanStatusCounters(v, addrExplain, addrExplain, pSort->addrPush); ++ + + assert( addrBreak<0 ); + if( pSort->labelBkOut ){ +@@ -137350,6 +143684,7 @@ static void generateSortTail( + VdbeComment((v, "%s", aOutEx[i].zEName)); + } + } ++ sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); + switch( eDest ){ + case SRT_Table: + case SRT_EphemTab: { +@@ -137411,6 +143746,7 @@ static void generateSortTail( + }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); + } +@@ -137419,9 +143755,6 @@ static void generateSortTail( + ** Return a pointer to a string containing the 'declaration type' of the + ** expression pExpr. The string may be treated as static by the caller. + ** +-** Also try to estimate the size of the returned value and return that +-** result in *pEstWidth. +-** + ** The declaration type is the exact datatype definition extracted from the + ** original CREATE TABLE statement if the expression is a column. The + ** declaration type for a ROWID field is INTEGER. Exactly when an expression +@@ -137675,17 +144008,10 @@ SQLITE_PRIVATE void sqlite3GenerateColumnNames( + 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 */ + +-#ifndef SQLITE_OMIT_EXPLAIN +- /* If this is an EXPLAIN, skip this step */ +- if( pParse->explain ){ +- return; +- } +-#endif +- + if( pParse->colNamesSet ) return; + /* Column names are determined by the left-most term of a compound select */ + while( pSelect->pPrior ) pSelect = pSelect->pPrior; +- SELECTTRACE(1,pParse,pSelect,("generating column names\n")); ++ TREETRACE(0x80,pParse,pSelect,("generating column names\n")); + pTabList = pSelect->pSrc; + pEList = pSelect->pEList; + assert( v!=0 ); +@@ -137785,7 +144111,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( + *pnCol = nCol; + *paCol = aCol; + +- for(i=0, pCol=aCol; i mallocFailed; i++, pCol++){ ++ for(i=0, pCol=aCol; i nErr; i++, pCol++){ + struct ExprList_item *pX = &pEList->a[i]; + struct ExprList_item *pCollide; + /* Get an appropriate name for the column +@@ -137835,7 +144161,10 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( + if( zName[j]==':' ) nName = j; + } + zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); +- if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); ++ sqlite3ProgressCheck(pParse); ++ if( cnt>3 ){ ++ sqlite3_randomness(sizeof(cnt), &cnt); ++ } + } + pCol->zCnName = zName; + pCol->hName = sqlite3StrIHash(zName); +@@ -137848,71 +144177,105 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( + } + } + sqlite3HashClear(&ht); +- if( db->mallocFailed ){ ++ if( pParse->nErr ){ + for(j=0; jrc; + } + return SQLITE_OK; + } + + /* +-** Add type and collation information to a column list based on +-** a SELECT statement. +-** +-** The column list presumably came from selectColumnNamesFromExprList(). +-** The column list has only names, not types or collations. This +-** routine goes through and adds the types and collations. ++** 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: + ** +-** This routine requires that all identifiers in the SELECT +-** statement be resolved. ++** * 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 sqlite3SelectAddColumnTypeAndCollation( +- 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 for columns */ ++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; +- NameContext sNC; + Column *pCol; + CollSeq *pColl; +- int i; ++ 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 || db->mallocFailed ); +- if( db->mallocFailed ) return; ++ testcase( (pSelect->selFlags & SF_Resolved)==0 ); ++ assert( (pSelect->selFlags & SF_Resolved)!=0 || IN_RENAME_OBJECT ); ++ 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; +- a = pSelect->pEList->a; + for(i=0, pCol=pTab->aCol; i nCol; i++, pCol++){ + const char *zType; +- i64 n, m; ++ i64 n; + pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); + p = a[i].pExpr; +- zType = columnType(&sNC, p, 0, 0, 0); + /* pCol->szEst = ... // Column size est for SELECT tables never used */ + pCol->affinity = sqlite3ExprAffinity(p); ++ if( pCol->affinity<=SQLITE_AFF_NONE ){ ++ pCol->affinity = aff; ++ } ++ if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){ ++ int m = 0; ++ Select *pS2; ++ for(m=0, pS2=pSelect->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; j affinity ){ ++ zType = sqlite3StdType[j]; ++ break; ++ } ++ } ++ } ++ } + if( zType ){ +- m = sqlite3Strlen30(zType); ++ i64 m = sqlite3Strlen30(zType); + n = sqlite3Strlen30(pCol->zCnName); + pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); ++ pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); + if( pCol->zCnName ){ + memcpy(&pCol->zCnName[n+1], zType, m+1); + pCol->colFlags |= COLFLAG_HASTYPE; +- }else{ +- testcase( pCol->colFlags & COLFLAG_HASTYPE ); +- pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); + } + } +- if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff; + pColl = sqlite3ExprCollSeq(pParse, p); + if( pColl ){ + assert( pTab->pIndex==0 ); +@@ -137946,7 +144309,7 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, c + pTab->zName = 0; + pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); + sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); +- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff); ++ sqlite3SubqueryColumnTypes(pParse, pTab, pSelect, aff); + pTab->iPKey = -1; + if( db->mallocFailed ){ + sqlite3DeleteTable(db, pTab); +@@ -138161,7 +144524,7 @@ static void generateWithRecursiveQuery( + int iQueue; /* The Queue table */ + int iDistinct = 0; /* To ensure unique results if UNION */ + int eDest = SRT_Fifo; /* How to write to Queue */ +- SelectDest destQueue; /* SelectDest targetting the Queue table */ ++ SelectDest destQueue; /* SelectDest targeting the Queue table */ + int i; /* Loop counter */ + int rc; /* Result code */ + ExprList *pOrderBy; /* The ORDER BY clause */ +@@ -138471,7 +144834,7 @@ static int multiSelect( + pPrior->iLimit = p->iLimit; + pPrior->iOffset = p->iOffset; + pPrior->pLimit = p->pLimit; +- SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n")); ++ TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); + rc = sqlite3Select(pParse, pPrior, &dest); + pPrior->pLimit = 0; + if( rc ){ +@@ -138489,7 +144852,7 @@ static int multiSelect( + } + } + ExplainQueryPlan((pParse, 1, "UNION ALL")); +- SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n")); ++ TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); + rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; +@@ -138542,7 +144905,7 @@ static int multiSelect( + */ + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); +- SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); ++ TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); + rc = sqlite3Select(pParse, pPrior, &uniondest); + if( rc ){ + goto multi_select_end; +@@ -138562,7 +144925,7 @@ static int multiSelect( + uniondest.eDest = op; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + sqlite3SelectOpName(p->op))); +- SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); ++ TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); + rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); + assert( p->pOrderBy==0 ); +@@ -138623,7 +144986,7 @@ static int multiSelect( + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); +- SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n")); ++ TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n")); + rc = sqlite3Select(pParse, pPrior, &intersectdest); + if( rc ){ + goto multi_select_end; +@@ -138640,7 +145003,7 @@ static int multiSelect( + intersectdest.iSDParm = tab2; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + sqlite3SelectOpName(p->op))); +- SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n")); ++ TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n")); + rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; +@@ -138737,9 +145100,7 @@ multi_select_end: + pDest->iSdst = dest.iSdst; + pDest->nSdst = dest.nSdst; + if( pDelete ){ +- sqlite3ParserAddCleanup(pParse, +- (void(*)(sqlite3*,void*))sqlite3SelectDelete, +- pDelete); ++ sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete); + } + return rc; + } +@@ -138761,7 +145122,7 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ + + /* + ** Code an output subroutine for a coroutine implementation of a +-** SELECT statment. ++** 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 +@@ -138983,7 +145344,7 @@ static int generateOutputSubroutine( + ** + ** 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" labe. AltB, AeqB, ++** 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 +@@ -139020,7 +145381,7 @@ static int multiSelectOrderBy( + 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 retargetted */ ++ 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 */ +@@ -139287,11 +145648,10 @@ static int multiSelectOrderBy( + */ + sqlite3VdbeResolveLabel(v, labelEnd); + +- /* Reassemble the compound query so that it will be freed correctly +- ** by the calling function */ ++ /* Make arrangements to free the 2nd and subsequent arms of the compound ++ ** after the parse has finished */ + if( pSplit->pPrior ){ +- sqlite3ParserAddCleanup(pParse, +- (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior); ++ sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSplit->pPrior); + } + pSplit->pPrior = pPrior; + pPrior->pNext = pSplit; +@@ -139321,7 +145681,7 @@ static int multiSelectOrderBy( + ** the left operands of a RIGHT JOIN. In either case, we need to potentially + ** bypass the substituted expression with OP_IfNullRow. + ** +-** Suppose the original expression integer constant. Even though the table ++** 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 +@@ -139347,6 +145707,7 @@ typedef struct SubstContext { + 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 */ +@@ -139388,19 +145749,26 @@ static Expr *substExpr( + #endif + { + Expr *pNew; +- Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr; ++ int iColumn; ++ Expr *pCopy; + Expr ifNullRow; +- assert( pSubst->pEList!=0 && pExpr->iColumn pEList->nExpr ); ++ iColumn = pExpr->iColumn; ++ assert( iColumn>=0 ); ++ assert( pSubst->pEList!=0 && iColumn pEList->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 ){ ++ 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; + } +@@ -139427,11 +145795,16 @@ static Expr *substExpr( + + /* Ensure that the expression now has an implicit collation sequence, + ** just as it did when it was a column of a view or sub-query. */ +- if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){ +- CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr); +- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr, +- (pColl ? pColl->zName : "BINARY") ++ { ++ CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr); ++ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, ++ pSubst->pCList->a[iColumn].pExpr + ); ++ if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){ ++ pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr, ++ (pColl ? pColl->zName : "BINARY") ++ ); ++ } + } + ExprClearProperty(pExpr, EP_Collate); + } +@@ -139624,6 +145997,46 @@ static void renumberCursors( + } + #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; ii nExpr; 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. +@@ -139668,7 +146081,8 @@ static void renumberCursors( + ** (3a) the subquery may not be a join and + ** (3b) the FROM clause of the subquery may not contain a virtual + ** table and +-** (3c) the outer query may not be an aggregate. ++** (**) 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. + ** +@@ -139691,7 +146105,7 @@ static void renumberCursors( + ** (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 +-** accidently carried the comment forward until 2014-09-15. Original ++** accidentally carried the comment forward until 2014-09-15. Original + ** constraint: "If the subquery is aggregate then the outer query + ** may not use LIMIT." + ** +@@ -139725,6 +146139,8 @@ static void renumberCursors( + ** (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, +@@ -139776,18 +146192,13 @@ static void renumberCursors( + ** See also (3) for restrictions on LEFT JOIN. + ** + ** (27) The subquery may not contain a FULL or RIGHT JOIN unless it +-** is the first element of the parent query. This must be the +-** the case if: +-** (27a) the subquery is not compound query, and ++** 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. +-** +-** (29) Either the subquery is not the right-hand operand of a join with an +-** ON or USING clause nor the right-hand operand of a NATURAL JOIN, or +-** the right-most table within the FROM clause of the subquery +-** is not part of an outer join. ++** (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. +@@ -139880,16 +146291,10 @@ static int flattenSubquery( + ** + ** which is not at all the same thing. + ** +- ** If the subquery is the right operand of a LEFT JOIN, then the outer +- ** query cannot be an aggregate. (3c) This is an artifact of the way +- ** aggregates are processed - there is no mechanism to determine if +- ** the LEFT JOIN table should be all-NULL. +- ** + ** See also tickets #306, #350, and #3300. + */ + if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ + if( pSubSrc->nSrc>1 /* (3a) */ +- || isAgg /* (3c) */ + || IsVirtual(pSubSrc->a[0].pTab) /* (3b) */ + || (p->selFlags & SF_Distinct)!=0 /* (3d) */ + || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */ +@@ -139898,52 +146303,14 @@ static int flattenSubquery( + } + isOuterJoin = 1; + } +-#ifdef SQLITE_EXTRA_IFNULLROW +- else if( iFrom>0 && !isAgg ){ +- /* Setting isOuterJoin to -1 causes OP_IfNullRow opcodes to be generated for +- ** every reference to any result column from subquery in a join, even +- ** though they are not necessary. This will stress-test the OP_IfNullRow +- ** opcode. */ +- isOuterJoin = -1; +- } +-#endif + + assert( pSubSrc->nSrc>0 ); /* True by restriction (7) */ + if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ + return 0; /* Restriction (27a) */ + } +- if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){ +- return 0; /* (28) */ +- } + +- /* Restriction (29): +- ** +- ** We do not want two constraints on the same term of the flattened +- ** query where one constraint has EP_InnerON and the other is EP_OuterON. +- ** To prevent this, one or the other of the following conditions must be +- ** false: +- ** +- ** (29a) The right-most entry in the FROM clause of the subquery +- ** must not be part of an outer join. +- ** +- ** (29b) The subquery itself must not be the right operand of a +- ** NATURAL join or a join that as an ON or USING clause. +- ** +- ** These conditions are sufficient to keep an EP_OuterON from being +- ** flattened into an EP_InnerON. Restrictions (3a) and (27a) prevent +- ** an EP_InnerON from being flattened into an EP_OuterON. +- */ +- if( pSubSrc->nSrc>=2 +- && (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0 +- ){ +- if( (pSubitem->fg.jointype & JT_NATURAL)!=0 +- || pSubitem->fg.isUsing +- || NEVER(pSubitem->u3.pOn!=0) /* ON clause already shifted into WHERE */ +- || pSubitem->fg.isOn +- ){ +- return 0; +- } +- } ++ /* 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 +@@ -139951,6 +146318,7 @@ static int flattenSubquery( + ** queries. + */ + if( pSub->pPrior ){ ++ int ii; + if( pSub->pOrderBy ){ + return 0; /* Restriction (20) */ + } +@@ -139983,7 +146351,6 @@ static int flattenSubquery( + + /* Restriction (18). */ + if( p->pOrderBy ){ +- int ii; + for(ii=0; ii pOrderBy->nExpr; ii++){ + if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0; + } +@@ -139992,6 +146359,9 @@ static int flattenSubquery( + /* 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; +@@ -140001,7 +146371,7 @@ static int flattenSubquery( + } + + /***** If we reach this point, flattening is permitted. *****/ +- SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n", ++ TREETRACE(0x4,pParse,p,("flatten %u.%p from term %d\n", + pSub->selId, pSub, iFrom)); + + /* Authorize the subquery */ +@@ -140010,7 +146380,7 @@ static int flattenSubquery( + testcase( i==SQLITE_DENY ); + pParse->zAuthContext = zSavedAuthContext; + +- /* Delete the transient structures associated with thesubquery */ ++ /* Delete the transient structures associated with the subquery */ + pSub1 = pSubitem->pSelect; + sqlite3DbFree(db, pSubitem->zDatabase); + sqlite3DbFree(db, pSubitem->zName); +@@ -140080,7 +146450,7 @@ static int flattenSubquery( + if( pPrior ) pPrior->pNext = pNew; + pNew->pNext = p; + p->pPrior = pNew; +- SELECTTRACE(2,pParse,p,("compound-subquery flattener" ++ TREETRACE(0x4,pParse,p,("compound-subquery flattener" + " creates %u as peer\n",pNew->selId)); + } + assert( pSubitem->pSelect==0 ); +@@ -140102,9 +146472,7 @@ static int flattenSubquery( + Table *pTabToDel = pSubitem->pTab; + if( pTabToDel->nTabRef==1 ){ + Parse *pToplevel = sqlite3ParseToplevel(pParse); +- sqlite3ParserAddCleanup(pToplevel, +- (void(*)(sqlite3*,void*))sqlite3DeleteTable, +- pTabToDel); ++ sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel); + testcase( pToplevel->earlyCleanup ); + }else{ + pTabToDel->nTabRef--; +@@ -140192,7 +146560,7 @@ static int flattenSubquery( + ** 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 transfering the ORDER BY clause. ++ ** 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 +@@ -140225,6 +146593,7 @@ static int flattenSubquery( + x.iNewTable = iNewParent; + x.isOuterJoin = isOuterJoin; + x.pEList = pSub->pEList; ++ x.pCList = findLeftmostExprlist(pSub); + substSelect(&x, pParent, 0); + } + +@@ -140244,23 +146613,22 @@ static int flattenSubquery( + pSub->pLimit = 0; + } + +- /* Recompute the SrcList_item.colUsed masks for the flattened ++ /* Recompute the SrcItem.colUsed masks for the flattened + ** tables. */ + for(i=0; i