diff options
74 files changed, 10606 insertions, 7014 deletions
diff --git a/application/palemoon/app.mozbuild b/application/palemoon/app.mozbuild index 0cbce0f72..1727d4f6b 100644 --- a/application/palemoon/app.mozbuild +++ b/application/palemoon/app.mozbuild @@ -13,5 +13,5 @@ DIRS += ['/%s' % CONFIG['MOZ_BRANDING_DIRECTORY']] # Never add tier dirs after browser because they apparently won't get # packaged properly on Mac. -DIRS += ['/browser'] +DIRS += ['/application/palemoon'] diff --git a/application/palemoon/app/blocklist.xml b/application/palemoon/app/blocklist.xml index 9c64af987..296b8ad24 100644 --- a/application/palemoon/app/blocklist.xml +++ b/application/palemoon/app/blocklist.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='utf-8'?> -<blocklist lastupdate="1508456048000" +<blocklist lastupdate="1521130300000" xmlns="http://www.mozilla.org/2006/addons-blocklist"> <emItems> <emItem blockID="i545" id="superlrcs@svenyor.net"> @@ -2441,6 +2441,18 @@ xmlns="http://www.mozilla.org/2006/addons-blocklist"> <versionRange minVersion="4.0.0a" maxVersion="4.1.20a" severity="1" /> </emItem> + <emItem blockID="2447476f-043b-4d0b-9d3c-8e859c97d950" id="{44e4b2cf-77ba-4f76-aca7-f3fcbc2dda2f}"> + <prefs/> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> + <emItem blockID="f58729ec-f93c-41d9-870d-dd9c9fd811b6" id="/^(addon@fasterweb\.com|\{5f398d3f-25db-47f5-b422-aa2364ff6c0b\}|addon@fasterp\.com|addon@calculator)$/"> + <prefs/> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> + <emItem blockID="3d55fab0-ec1a-4bca-84c9-3b74f5d01509" id="/^.*extension.*@asdf\.pl$/"> + <prefs/> + <versionRange minVersion="0" maxVersion="*" severity="3"/> + </emItem> <emItem blockID="pm100" id="{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> diff --git a/application/palemoon/app/macbuild/Contents/Info.plist.in b/application/palemoon/app/macbuild/Contents/Info.plist.in index c77ab1ec5..b224064cf 100644 --- a/application/palemoon/app/macbuild/Contents/Info.plist.in +++ b/application/palemoon/app/macbuild/Contents/Info.plist.in @@ -205,6 +205,11 @@ <true/> <key>LSApplicationCategoryType</key> <string>public.app-category.productivity</string> + <key>LSEnvironment</key> + <dict> + <key>MallocNanoZone</key> + <string>0</string> + </dict> <key>LSMinimumSystemVersion</key> <string>10.6</string> <key>LSMinimumSystemVersionByArchitecture</key> diff --git a/application/palemoon/app/moz.build b/application/palemoon/app/moz.build index 929139a6a..f9955c097 100644 --- a/application/palemoon/app/moz.build +++ b/application/palemoon/app/moz.build @@ -7,10 +7,7 @@ DIRS += ['profile/extensions'] -if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_ASAN']: - GoannaProgram(CONFIG['MOZ_APP_NAME']) -else: - GoannaProgram(CONFIG['MOZ_APP_NAME'], msvcrt='static') +GeckoProgram(CONFIG['MOZ_APP_NAME']) JS_PREFERENCE_FILES += [ 'profile/palemoon.js', @@ -30,14 +27,8 @@ FINAL_TARGET_FILES.defaults.profile += ['profile/prefs.js'] DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] -for var in ('MOZILLA_OFFICIAL', 'LIBXUL_SDK'): - if CONFIG[var]: - DEFINES[var] = True - -DEFINES['XPCOM_GLUE'] = True - -GENERATED_INCLUDES += [ - '/build', +LOCAL_INCLUDES += [ + '!/build', ] LOCAL_INCLUDES += [ @@ -46,11 +37,9 @@ LOCAL_INCLUDES += [ '/xpcom/build', ] -DELAYLOAD_DLLS += [ - 'mozglue.dll', +USE_LIBS += [ + 'mozglue', ] -USE_STATIC_LIBS = True - if CONFIG['_MSC_VER']: # Always enter a Windows program through wmain, whether or not we're @@ -72,16 +61,6 @@ if CONFIG['OS_ARCH'] == 'WINNT': if CONFIG['OS_ARCH'] == 'WINNT' and not CONFIG['GNU_CC']: LDFLAGS += ['/HEAP:0x40000'] -if CONFIG['OS_ARCH'] == 'WINNT': - USE_LIBS += [ - 'mozglue', - 'xpcomglue_staticruntime', - ] -else: - USE_LIBS += [ - 'xpcomglue', - ] - DISABLE_STL_WRAPPING = True if CONFIG['MOZ_LINKER']: diff --git a/application/palemoon/app/nsBrowserApp.cpp b/application/palemoon/app/nsBrowserApp.cpp index f9645b0c6..1f8bd4580 100644 --- a/application/palemoon/app/nsBrowserApp.cpp +++ b/application/palemoon/app/nsBrowserApp.cpp @@ -8,25 +8,13 @@ #include "application.ini.h" #include "nsXPCOMGlue.h" #if defined(XP_WIN) -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 #include <windows.h> -#include <winbase.h> -#include <VersionHelpers.h> #include <stdlib.h> -#include <io.h> -#include <fcntl.h> #elif defined(XP_UNIX) #include <sys/resource.h> -#include <time.h> #include <unistd.h> #endif -#ifdef XP_MACOSX -#include <mach/mach_time.h> -#include "MacQuirks.h" -#endif - #include <stdio.h> #include <stdarg.h> #include <time.h> @@ -35,20 +23,31 @@ #include "nsIFile.h" #include "nsStringGlue.h" -// Easy access to a five second startup delay used to get -// a debugger attached in the metro environment. -// #define DEBUG_delay_start_metro - #ifdef XP_WIN -// we want a wmain entry point -#include "nsWindowsWMain.cpp" -#define snprintf _snprintf +#ifdef MOZ_ASAN +// ASAN requires palemoon.exe to be built with -MD, and it's OK if we don't +// support Windows XP SP2 in ASAN builds. +#define XRE_DONT_SUPPORT_XPSP2 +#endif +#define XRE_WANT_ENVIRON #define strcasecmp _stricmp +#ifdef MOZ_SANDBOX +#include "mozilla/sandboxing/SandboxInitialization.h" +#endif #endif #include "BinaryPath.h" #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL -#include "mozilla/StartupTimeline.h" + +#include "mozilla/Sprintf.h" +#include "mozilla/Telemetry.h" +#include "mozilla/WindowsDllBlocklist.h" + +#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \ + && !(defined(XP_LINUX) && defined(MOZ_SANDBOX)) +#define MOZ_BROWSER_CAN_BE_CONTENTPROC +#include "../../ipc/contentproc/plugin-container.cpp" +#endif using namespace mozilla; @@ -56,12 +55,6 @@ using namespace mozilla; #define kOSXResourcesFolder "Resources" #endif #define kDesktopFolder "browser" -#define kMetroFolder "metro" -#define kMetroAppIniFilename "metroapp.ini" -#ifdef XP_WIN -#define kMetroTestFile "tests.ini" -const char* kMetroConsoleIdParam = "testconsoleid="; -#endif static void Output(const char *fmt, ... ) { @@ -84,10 +77,19 @@ static void Output(const char *fmt, ... ) #if MOZ_WINCONSOLE fwprintf_s(stderr, wide_msg); #else - MessageBoxW(nullptr, - wide_msg, - L"Pale Moon", - MB_OK | MB_ICONERROR | MB_SETFOREGROUND); + // Linking user32 at load-time interferes with the DLL blocklist (bug 932100). + // This is a rare codepath, so we can load user32 at run-time instead. + HMODULE user32 = LoadLibraryW(L"user32.dll"); + if (user32) { + decltype(MessageBoxW)* messageBoxW = + (decltype(MessageBoxW)*) GetProcAddress(user32, "MessageBoxW"); + if (messageBoxW) { + messageBoxW(nullptr, wide_msg, L"Pale Moon", MB_OK + | MB_ICONERROR + | MB_SETFOREGROUND); + } + FreeLibrary(user32); + } #endif #endif @@ -114,76 +116,60 @@ static bool IsArg(const char* arg, const char* s) return false; } -#ifdef XP_WIN -/* - * AttachToTestHarness - Windows helper for when we are running - * in the immersive environment. Firefox is launched by Windows in - * response to a request by metrotestharness, which is launched by - * runtests.py. As such stdout in fx doesn't point to the right - * stream. This helper touches up stdout such that test output gets - * routed to a named pipe metrotestharness creates and dumps to its - * stdout. - */ -static void AttachToTestHarness() -{ - // attach to the metrotestharness named logging pipe - HANDLE winOut = CreateFileA("\\\\.\\pipe\\metrotestharness", - GENERIC_WRITE, - FILE_SHARE_WRITE, 0, - OPEN_EXISTING, 0, 0); - - if (winOut == INVALID_HANDLE_VALUE) { - OutputDebugStringW(L"Could not create named logging pipe.\n"); - return; - } - - // Set the c runtime handle - int stdOut = _open_osfhandle((intptr_t)winOut, _O_APPEND); - if (stdOut == -1) { - OutputDebugStringW(L"Could not open c-runtime handle.\n"); - return; - } - FILE *fp = _fdopen(stdOut, "a"); - *stdout = *fp; -} -#endif - XRE_GetFileFromPathType XRE_GetFileFromPath; XRE_CreateAppDataType XRE_CreateAppData; XRE_FreeAppDataType XRE_FreeAppData; -#ifdef XRE_HAS_DLL_BLOCKLIST -XRE_SetupDllBlocklistType XRE_SetupDllBlocklist; -#endif +XRE_TelemetryAccumulateType XRE_TelemetryAccumulate; XRE_StartupTimelineRecordType XRE_StartupTimelineRecord; XRE_mainType XRE_main; XRE_StopLateWriteChecksType XRE_StopLateWriteChecks; +XRE_XPCShellMainType XRE_XPCShellMain; +XRE_GetProcessTypeType XRE_GetProcessType; +XRE_SetProcessTypeType XRE_SetProcessType; +XRE_InitChildProcessType XRE_InitChildProcess; +XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc; +#ifdef LIBFUZZER +XRE_LibFuzzerSetMainType XRE_LibFuzzerSetMain; +XRE_LibFuzzerGetFuncsType XRE_LibFuzzerGetFuncs; +#endif static const nsDynamicFunctionLoad kXULFuncs[] = { { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData }, -#ifdef XRE_HAS_DLL_BLOCKLIST - { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist }, -#endif + { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate }, { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord }, { "XRE_main", (NSFuncPtr*) &XRE_main }, { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks }, + { "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain }, + { "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType }, + { "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType }, + { "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess }, + { "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc }, +#ifdef LIBFUZZER + { "XRE_LibFuzzerSetMain", (NSFuncPtr*) &XRE_LibFuzzerSetMain }, + { "XRE_LibFuzzerGetFuncs", (NSFuncPtr*) &XRE_LibFuzzerGetFuncs }, +#endif { nullptr, nullptr } }; -static int do_main(int argc, char* argv[], nsIFile *xreDirectory) +#ifdef LIBFUZZER +int libfuzzer_main(int argc, char **argv); + +/* This wrapper is used by the libFuzzer main to call into libxul */ + +void libFuzzerGetFuncs(const char* moduleName, LibFuzzerInitFunc* initFunc, + LibFuzzerTestingFunc* testingFunc) { + return XRE_LibFuzzerGetFuncs(moduleName, initFunc, testingFunc); +} +#endif + +static int do_main(int argc, char* argv[], char* envp[], nsIFile *xreDirectory) { nsCOMPtr<nsIFile> appini; nsresult rv; uint32_t mainFlags = 0; -#ifdef XP_WIN - if (!IsWindowsVistaOrGreater()) { - Output("Couldn't load valid PE image.\n"); - return 255; - } - -#endif // Allow palemoon.exe to launch XULRunner apps via -app <application.ini> // Note that -app must be the *first* argument. const char *appDataFile = getenv("XUL_APP_FILE"); @@ -207,14 +193,26 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory) } char appEnv[MAXPATHLEN]; - snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]); - if (putenv(appEnv)) { + SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]); + if (putenv(strdup(appEnv))) { Output("Couldn't set %s.\n", appEnv); return 255; } argv[2] = argv[0]; argv += 2; argc -= 2; + } else if (argc > 1 && IsArg(argv[1], "xpcshell")) { + for (int i = 1; i < argc; i++) { + argv[i] = argv[i + 1]; + } + + XREShellData shellData; +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + shellData.sandboxBrokerServices = + sandboxing::GetInitializedBrokerServices(); +#endif + + return XRE_XPCShellMain(--argc, argv, envp, &shellData); } if (appini) { @@ -224,6 +222,13 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory) Output("Couldn't read application.ini"); return 255; } +#if defined(HAS_DLL_BLOCKLIST) + // The dll blocklist operates in the exe vs. xullib. Pass a flag to + // xullib so automated tests can check the result once the browser + // is up and running. + appData->flags |= + DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0; +#endif // xreDirectory already has a refcount from NS_NewLocalFile appData->xreDirectory = xreDirectory; int result = XRE_main(argc, argv, appData, mainFlags); @@ -231,7 +236,6 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory) return result; } - // Desktop browser launch ScopedAppData appData(&sAppData); nsCOMPtr<nsIFile> exeFile; rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile)); @@ -243,10 +247,7 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory) nsCOMPtr<nsIFile> greDir; exeFile->GetParent(getter_AddRefs(greDir)); #ifdef XP_MACOSX - nsCOMPtr<nsIFile> parent; - greDir->GetParent(getter_AddRefs(parent)); - greDir = parent.forget(); - greDir->AppendNative(NS_LITERAL_CSTRING(kOSXResourcesFolder)); + greDir->SetNativeLeafName(NS_LITERAL_CSTRING(kOSXResourcesFolder)); #endif nsCOMPtr<nsIFile> appSubdir; greDir->Clone(getter_AddRefs(appSubdir)); @@ -256,33 +257,29 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory) // xreDirectory already has a refcount from NS_NewLocalFile appData.xreDirectory = xreDirectory; - return XRE_main(argc, argv, &appData, mainFlags); -} +#if defined(HAS_DLL_BLOCKLIST) + appData.flags |= + DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0; +#endif -/** - * Local TimeStamp::Now()-compatible implementation used to record timestamps - * which will be passed to XRE_StartupTimelineRecord(). - */ -static uint64_t -TimeStamp_Now() -{ -#ifdef XP_WIN - LARGE_INTEGER freq; - ::QueryPerformanceFrequency(&freq); - return GetTickCount64() * freq.QuadPart; -#elif defined(XP_MACOSX) - return mach_absolute_time(); -#elif defined(HAVE_CLOCK_MONOTONIC) - struct timespec ts; - int rv = clock_gettime(CLOCK_MONOTONIC, &ts); - - if (rv != 0) { - return 0; +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + sandbox::BrokerServices* brokerServices = + sandboxing::GetInitializedBrokerServices(); +#if defined(MOZ_CONTENT_SANDBOX) + if (!brokerServices) { + Output("Couldn't initialize the broker services.\n"); + return 255; } +#endif + appData.sandboxBrokerServices = brokerServices; +#endif - uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000; - return baseNs + (uint64_t)ts.tv_nsec; +#ifdef LIBFUZZER + if (getenv("LIBFUZZER")) + XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main); #endif + + return XRE_main(argc, argv, &appData, mainFlags); } static bool @@ -298,11 +295,6 @@ FileExists(const char *path) #endif } -#ifdef LIBXUL_SDK -# define XPCOM_PATH "xulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL -#else -# define XPCOM_PATH XPCOM_DLL -#endif static nsresult InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory) { @@ -315,55 +307,13 @@ InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory) } char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); - if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_PATH) - 1)) + if (!lastSlash || + (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1)) return NS_ERROR_FAILURE; - strcpy(lastSlash + 1, XPCOM_PATH); - lastSlash += sizeof(XPCOM_PATH) - sizeof(XPCOM_DLL); + strcpy(lastSlash + 1, XPCOM_DLL); if (!FileExists(exePath)) { -#if defined(LIBXUL_SDK) && defined(XP_MACOSX) - // Check for <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib - bool greFound = false; - CFBundleRef appBundle = CFBundleGetMainBundle(); - if (!appBundle) - return NS_ERROR_FAILURE; - CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle); - CFURLRef absfwurl = nullptr; - if (fwurl) { - absfwurl = CFURLCopyAbsoluteURL(fwurl); - CFRelease(fwurl); - } - if (absfwurl) { - CFURLRef xulurl = - CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl, - CFSTR("XUL.framework"), - true); - - if (xulurl) { - CFURLRef xpcomurl = - CFURLCreateCopyAppendingPathComponent(nullptr, xulurl, - CFSTR("libxpcom.dylib"), - false); - - if (xpcomurl) { - if (CFURLGetFileSystemRepresentation(xpcomurl, true, - (UInt8*) exePath, - sizeof(exePath)) && - access(tbuffer, R_OK | X_OK) == 0) { - if (realpath(tbuffer, exePath)) { - greFound = true; - } - } - CFRelease(xpcomurl); - } - CFRelease(xulurl); - } - CFRelease(absfwurl); - } - } - if (!greFound) { -#endif Output("Could not find the Mozilla runtime.\n"); return NS_ERROR_FAILURE; } @@ -383,45 +333,72 @@ InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory) return rv; } + // This will set this thread as the main thread. NS_LogInit(); - // chop XPCOM_DLL off exePath - *lastSlash = '\0'; + if (xreDirectory) { + // chop XPCOM_DLL off exePath + *lastSlash = '\0'; #ifdef XP_MACOSX - lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); - strcpy(lastSlash + 1, kOSXResourcesFolder); + lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); + strcpy(lastSlash + 1, kOSXResourcesFolder); #endif #ifdef XP_WIN - rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false, - xreDirectory); + rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false, + xreDirectory); #else - rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false, - xreDirectory); + rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false, + xreDirectory); #endif + } return rv; } -int main(int argc, char* argv[]) +int main(int argc, char* argv[], char* envp[]) { -#ifdef DEBUG_delay_start_metro - Sleep(5000); + mozilla::TimeStamp start = mozilla::TimeStamp::Now(); + +#ifdef HAS_DLL_BLOCKLIST + DllBlocklist_Initialize(); + +#ifdef DEBUG + // In order to be effective against AppInit DLLs, the blocklist must be + // initialized before user32.dll is loaded into the process (bug 932100). + if (GetModuleHandleA("user32.dll")) { + fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n"); + } +#endif #endif - uint64_t start = TimeStamp_Now(); -#ifdef XP_MACOSX - TriggerQuirks(); +#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC + // We are launching as a content process, delegate to the appropriate + // main + if (argc > 1 && IsArg(argv[1], "contentproc")) { +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + // We need to initialize the sandbox TargetServices before InitXPCOMGlue + // because we might need the sandbox broker to give access to some files. + if (IsSandboxedProcess() && !sandboxing::GetInitializedTargetServices()) { + Output("Failed to initialize the sandbox target services."); + return 255; + } #endif - int gotCounters; -#if defined(XP_UNIX) - struct rusage initialRUsage; - gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage); -#elif defined(XP_WIN) - IO_COUNTERS ioCounters; - gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters); + nsresult rv = InitXPCOMGlue(argv[0], nullptr); + if (NS_FAILED(rv)) { + return 255; + } + + int result = content_process_main(argc, argv); + + // InitXPCOMGlue calls NS_LogInit, so we need to balance it here. + NS_LogTerm(); + + return result; + } #endif + nsIFile *xreDirectory; nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory); @@ -431,11 +408,11 @@ int main(int argc, char* argv[]) XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start); -#ifdef XRE_HAS_DLL_BLOCKLIST - XRE_SetupDllBlocklist(); +#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC + XRE_EnableSameExecutableForContentProc(); #endif - int result = do_main(argc, argv, xreDirectory); + int result = do_main(argc, argv, envp, xreDirectory); NS_LogTerm(); diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 34b91b6cb..5a832c077 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -336,6 +336,48 @@ const gSessionHistoryObserver = { } }; +var gURLBarSettings = { + prefSuggest: "browser.urlbar.suggest.", + /* + For searching in the source code: + browser.urlbar.suggest.bookmark + browser.urlbar.suggest.history + browser.urlbar.suggest.openpage + */ + prefSuggests: [ + "bookmark", + "history", + "openpage" + ], + prefKeyword: "keyword.enabled", + + observe: function(aSubject, aTopic, aData) { + if (aTopic != "nsPref:changed") + return; + + this.writePlaceholder(); + }, + + writePlaceholder: function() { + let attribute = "placeholder"; + let prefs = this.prefSuggests.map(pref => { + return this.prefSuggest + pref; + }); + prefs.push(this.prefKeyword); + let placeholderDefault = prefs.some(pref => { + return gPrefService.getBoolPref(pref); + }); + + if (placeholderDefault) { + gURLBar.setAttribute( + attribute, gNavigatorBundle.getString("urlbar.placeholder")); + } else { + gURLBar.setAttribute( + attribute, gNavigatorBundle.getString("urlbar.placeholderURLOnly")); + } + } +}; + /** * Given a starting docshell and a URI to look up, find the docshell the URI * is loaded in. @@ -968,6 +1010,11 @@ var gBrowserInit = { Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false); Services.obs.addObserver(gXSSObserver, "xss-on-violate-policy", false); + gPrefService.addObserver(gURLBarSettings.prefSuggest, gURLBarSettings, false); + gPrefService.addObserver(gURLBarSettings.prefKeyword, gURLBarSettings, false); + + gURLBarSettings.writePlaceholder(); + BrowserOffline.init(); OfflineApps.init(); IndexedDBPromptHelper.init(); @@ -1314,6 +1361,13 @@ var gBrowserInit = { Services.obs.removeObserver(gXSSObserver, "xss-on-violate-policy"); try { + gPrefService.removeObserver(gURLBarSettings.prefSuggest, gURLBarSettings); + gPrefService.removeObserver(gURLBarSettings.prefKeyword, gURLBarSettings); + } catch (ex) { + Cu.reportError(ex); + } + + try { gPrefService.removeObserver(gHomeButton.prefDomain, gHomeButton); } catch (ex) { Cu.reportError(ex); diff --git a/application/palemoon/base/content/browser.xul b/application/palemoon/base/content/browser.xul index f83010023..3044ce675 100644 --- a/application/palemoon/base/content/browser.xul +++ b/application/palemoon/base/content/browser.xul @@ -410,7 +410,7 @@ <toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true" title="&locationItem.title;" class="chromeclass-location" removable="true"> <textbox id="urlbar" flex="1" - placeholder="&urlbar.placeholder2;" + placeholder="" type="autocomplete" autocompletesearch="urlinline history" autocompletesearchparam="enable-actions" diff --git a/application/palemoon/base/content/content.js b/application/palemoon/base/content/content.js index 19032eb84..3587bbeef 100644 --- a/application/palemoon/base/content/content.js +++ b/application/palemoon/base/content/content.js @@ -61,4 +61,8 @@ addEventListener("blur", function(event) { addMessageListener("Finder:Initialize", function () { let {RemoteFinderListener} = Cu.import("resource://gre/modules/RemoteFinder.jsm", {}); new RemoteFinderListener(global); -});
\ No newline at end of file +}); + +addEventListener("DOMWebNotificationClicked", function(event) { + sendAsyncMessage("DOMWebNotificationClicked", {}); +}, false); diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml index b8d5f3e41..51f7063f3 100644 --- a/application/palemoon/base/content/tabbrowser.xml +++ b/application/palemoon/base/content/tabbrowser.xml @@ -2950,13 +2950,23 @@ let browser = aMessage.target; switch (aMessage.name) { - case "DOMTitleChanged": + case "DOMTitleChanged": { let tab = this.getTabForBrowser(browser); if (!tab) return; let titleChanged = this.setTabTitle(tab); if (titleChanged && !tab.selected && !tab.hasAttribute("busy")) tab.setAttribute("titlechanged", "true"); + break; + } + case "DOMWebNotificationClicked": { + let tab = this.getTabForBrowser(browser); + if (!tab) + return; + this.selectedTab = tab; + window.focus(); + break; + } } ]]></body> </method> @@ -3022,6 +3032,7 @@ this._outerWindowIDBrowserMap.set(this.mCurrentBrowser.outerWindowID, this.mCurrentBrowser); } + messageManager.addMessageListener("DOMWebNotificationClicked", this); ]]> </constructor> diff --git a/application/palemoon/branding/official/moz.build b/application/palemoon/branding/official/moz.build index 847510ec0..8cb90130f 100644 --- a/application/palemoon/branding/official/moz.build +++ b/application/palemoon/branding/official/moz.build @@ -4,4 +4,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +DIRS += ['content', 'locales'] + +DIST_SUBDIR = 'browser' +export('DIST_SUBDIR') + include('../shared/branding.mozbuild') +ApplicationBranding() diff --git a/application/palemoon/branding/shared/branding.mozbuild b/application/palemoon/branding/shared/branding.mozbuild index 0636be64a..0b99ec223 100644 --- a/application/palemoon/branding/shared/branding.mozbuild +++ b/application/palemoon/branding/shared/branding.mozbuild @@ -4,52 +4,49 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -DIRS += ['content', 'locales'] - -DIST_SUBDIR = 'browser' -export('DIST_SUBDIR') - -JS_PREFERENCE_FILES += [ - 'pref/palemoon-branding.js', -] - -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': - FINAL_TARGET_FILES['..'] += [ - 'palemoon.VisualElementsManifest.xml', - ] - FINAL_TARGET_FILES.VisualElements += [ - 'VisualElements_150.png', - 'VisualElements_70.png', - ] - BRANDING_FILES += [ - '../shared/newtab.ico', - '../shared/newwindow.ico', - '../shared/pbmode.ico', - 'appname.bmp', - 'branding.nsi', - 'document.ico', - 'firefox.ico', - 'wizHeader.bmp', - 'wizHeaderRTL.bmp', - 'wizWatermark.bmp', - ] -elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': - BRANDING_FILES += [ - '../shared/background.png', - 'disk.icns', - 'document.icns', - 'dsstore', - 'firefox.icns', - ] -elif CONFIG['MOZ_WIDGET_GTK']: - BRANDING_FILES += [ - 'default16.png', - 'default32.png', - 'default48.png', - 'mozicon128.png', +@template +def ApplicationBranding(): + JS_PREFERENCE_FILES += [ + 'pref/palemoon-branding.js', ] -DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] -DEFINES['MOZ_BRANDING_DIRECTORY'] = CONFIG['MOZ_BRANDING_DIRECTORY'] -DEFINES['MOZILLA_UAVERSION_U'] = CONFIG['MOZILLA_UAVERSION_U'] -DEFINES['MOZILLA_COMPATVERSION_U'] = CONFIG['MOZILLA_COMPATVERSION_U']
\ No newline at end of file + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + FINAL_TARGET_FILES['..'] += [ + 'palemoon.VisualElementsManifest.xml', + ] + FINAL_TARGET_FILES.VisualElements += [ + 'VisualElements_150.png', + 'VisualElements_70.png', + ] + BRANDING_FILES += [ + '../shared/newtab.ico', + '../shared/newwindow.ico', + '../shared/pbmode.ico', + 'appname.bmp', + 'branding.nsi', + 'document.ico', + 'firefox.ico', + 'wizHeader.bmp', + 'wizHeaderRTL.bmp', + 'wizWatermark.bmp', + ] + elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + BRANDING_FILES += [ + '../shared/background.png', + 'disk.icns', + 'document.icns', + 'dsstore', + 'firefox.icns', + ] + elif CONFIG['MOZ_WIDGET_GTK']: + BRANDING_FILES += [ + 'default16.png', + 'default32.png', + 'default48.png', + 'mozicon128.png', + ] + + DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] + DEFINES['MOZ_BRANDING_DIRECTORY'] = CONFIG['MOZ_BRANDING_DIRECTORY'] + DEFINES['MOZILLA_UAVERSION_U'] = CONFIG['MOZILLA_UAVERSION_U'] + DEFINES['MOZILLA_COMPATVERSION_U'] = CONFIG['MOZILLA_COMPATVERSION_U']
\ No newline at end of file diff --git a/application/palemoon/branding/shared/pref/uaoverrides.inc b/application/palemoon/branding/shared/pref/uaoverrides.inc index 20cc3ab86..db9ccaffa 100644 --- a/application/palemoon/branding/shared/pref/uaoverrides.inc +++ b/application/palemoon/branding/shared/pref/uaoverrides.inc @@ -36,6 +36,7 @@ pref("@GUAO_PREF@.yahoo.com","Mozilla/5.0 (@OS_SLICE@ rv:99.9) @GK_SLICE@ Firefo pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (@OS_SLICE@ rv:42.0) @GK_SLICE@ Firefox/42.0 @PM_SLICE@");
pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (@OS_SLICE@ rv:42.0) @GK_SLICE@ Firefox/42.0");
+pref("@GUAO_PREF@.dropbox.com","Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko");
pref("@GUAO_PREF@.players.brightcove.net","Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko");
// The never-ending Facebook debacle...
@@ -60,7 +61,6 @@ pref("@GUAO_PREF@.dailymotion.com","Mozilla/5.0 (@OS_SLICE@ rv:52.0) @GK_SLICE@ // The following requires native mode. Or it blocks.. "too old firefox", breakage, etc.
pref("@GUAO_PREF@.deviantart.com","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
pref("@GUAO_PREF@.deviantart.net","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
-pref("@GUAO_PREF@.dropbox.com","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
// UA-Sniffing domains below have indicated no interest in supporting Pale Moon (BOO!)
pref("@GUAO_PREF@.humblebundle.com","Mozilla/5.0 (@OS_SLICE@ rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
diff --git a/application/palemoon/branding/unofficial/moz.build b/application/palemoon/branding/unofficial/moz.build index 847510ec0..8cb90130f 100644 --- a/application/palemoon/branding/unofficial/moz.build +++ b/application/palemoon/branding/unofficial/moz.build @@ -4,4 +4,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +DIRS += ['content', 'locales'] + +DIST_SUBDIR = 'browser' +export('DIST_SUBDIR') + include('../shared/branding.mozbuild') +ApplicationBranding() diff --git a/application/palemoon/branding/unstable/moz.build b/application/palemoon/branding/unstable/moz.build index 847510ec0..8cb90130f 100644 --- a/application/palemoon/branding/unstable/moz.build +++ b/application/palemoon/branding/unstable/moz.build @@ -4,4 +4,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +DIRS += ['content', 'locales'] + +DIST_SUBDIR = 'browser' +export('DIST_SUBDIR') + include('../shared/branding.mozbuild') +ApplicationBranding() diff --git a/application/palemoon/build.mk b/application/palemoon/build.mk index fc692eda5..ae490aca7 100644 --- a/application/palemoon/build.mk +++ b/application/palemoon/build.mk @@ -3,40 +3,40 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. installer: - @$(MAKE) -C browser/installer installer + @$(MAKE) -C application/palemoon/installer installer package: - @$(MAKE) -C browser/installer + @$(MAKE) -C application/palemoon/installer package-compare: - @$(MAKE) -C browser/installer package-compare + @$(MAKE) -C application/palemoon/installer package-compare stage-package: - @$(MAKE) -C browser/installer stage-package + @$(MAKE) -C application/palemoon/installer stage-package install:: - @$(MAKE) -C browser/installer install + @$(MAKE) -C application/palemoon/installer install clean:: - @$(MAKE) -C browser/installer clean + @$(MAKE) -C application/palemoon/installer clean distclean:: - @$(MAKE) -C browser/installer distclean + @$(MAKE) -C application/palemoon/installer distclean source-package:: - @$(MAKE) -C browser/installer source-package + @$(MAKE) -C application/palemoon/installer source-package upload:: - @$(MAKE) -C browser/installer upload + @$(MAKE) -C application/palemoon/installer upload source-upload:: - @$(MAKE) -C browser/installer source-upload + @$(MAKE) -C application/palemoon/installer source-upload hg-bundle:: - @$(MAKE) -C browser/installer hg-bundle + @$(MAKE) -C application/palemoon/installer hg-bundle l10n-check:: - @$(MAKE) -C browser/locales l10n-check + @$(MAKE) -C application/palemoon/locales l10n-check ifdef ENABLE_TESTS # Implemented in testing/testsuite-targets.mk diff --git a/application/palemoon/components/about/AboutRedirector.cpp b/application/palemoon/components/about/AboutRedirector.cpp index d927b7936..b5dd4abfb 100644 --- a/application/palemoon/components/about/AboutRedirector.cpp +++ b/application/palemoon/components/about/AboutRedirector.cpp @@ -9,8 +9,6 @@ #include "nsNetUtil.h" #include "nsIScriptSecurityManager.h" #include "mozilla/ArrayUtils.h" -#include "nsDOMString.h" - namespace mozilla { namespace browser { @@ -21,7 +19,6 @@ struct RedirEntry { const char* id; const char* url; uint32_t flags; - const char* idbOriginPostfix; }; /* @@ -148,30 +145,6 @@ AboutRedirector::GetURIFlags(nsIURI *aURI, uint32_t *result) return NS_ERROR_ILLEGAL_VALUE; } -NS_IMETHODIMP -AboutRedirector::GetIndexedDBOriginPostfix(nsIURI *aURI, nsAString &result) -{ - NS_ENSURE_ARG_POINTER(aURI); - - nsAutoCString name = GetAboutModuleName(aURI); - - for (int i = 0; i < kRedirTotal; i++) { - if (name.Equals(kRedirMap[i].id)) { - const char* postfix = kRedirMap[i].idbOriginPostfix; - if (!postfix) { - break; - } - - result.AssignASCII(postfix); - return NS_OK; - } - } - - SetDOMStringToNull(result); - return NS_ERROR_ILLEGAL_VALUE; -} - - nsresult AboutRedirector::Create(nsISupports *aOuter, REFNSIID aIID, void **result) { diff --git a/application/palemoon/components/build/moz.build b/application/palemoon/components/build/moz.build index f8073907e..5bc4858d7 100644 --- a/application/palemoon/components/build/moz.build +++ b/application/palemoon/components/build/moz.build @@ -24,11 +24,17 @@ LOCAL_INCLUDES += [ if CONFIG['OS_ARCH'] == 'WINNT': OS_LIBS += [ + 'esent', + 'netapi32', 'ole32', 'shell32', 'shlwapi', 'version', ] + DELAYLOAD_DLLS += [ + 'esent.dll', + 'netapi32.dll', + ] # Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code) # GTK2: Need to link with glib for GNOME shell service diff --git a/application/palemoon/components/dirprovider/DirectoryProvider.cpp b/application/palemoon/components/dirprovider/DirectoryProvider.cpp index 4d3993b7f..85728b351 100644 --- a/application/palemoon/components/dirprovider/DirectoryProvider.cpp +++ b/application/palemoon/components/dirprovider/DirectoryProvider.cpp @@ -34,57 +34,7 @@ NS_IMPL_ISUPPORTS(DirectoryProvider, NS_IMETHODIMP DirectoryProvider::GetFile(const char *aKey, bool *aPersist, nsIFile* *aResult) { - nsresult rv; - - *aResult = nullptr; - - // NOTE: This function can be reentrant through the NS_GetSpecialDirectory - // call, so be careful not to cause infinite recursion. - - nsCOMPtr<nsIFile> file; - - char const* leafName = nullptr; - - if (!strcmp(aKey, NS_APP_BOOKMARKS_50_FILE)) { - leafName = "bookmarks.html"; - - nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (prefs) { - nsCString path; - rv = prefs->GetCharPref("browser.bookmarks.file", getter_Copies(path)); - if (NS_SUCCEEDED(rv)) { - NS_NewNativeLocalFile(path, true, getter_AddRefs(file)); - } - } - } - else { - return NS_ERROR_FAILURE; - } - - nsDependentCString leafstr(leafName); - - nsCOMPtr<nsIFile> parentDir; - if (file) { - rv = file->GetParent(getter_AddRefs(parentDir)); - if (NS_FAILED(rv)) - return rv; - } - else { - rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(parentDir)); - if (NS_FAILED(rv)) - return rv; - - rv = parentDir->Clone(getter_AddRefs(file)); - if (NS_FAILED(rv)) - return rv; - - file->AppendNative(leafstr); - } - - *aPersist = true; - NS_ADDREF(*aResult = file); - - return NS_OK; + return NS_ERROR_FAILURE; } static void diff --git a/application/palemoon/components/feeds/moz.build b/application/palemoon/components/feeds/moz.build index 1dea0ce77..7ae9141aa 100644 --- a/application/palemoon/components/feeds/moz.build +++ b/application/palemoon/components/feeds/moz.build @@ -35,5 +35,3 @@ for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'): LOCAL_INCLUDES += [ '../build', ] - -FAIL_ON_WARNINGS = True diff --git a/application/palemoon/components/feeds/nsFeedSniffer.cpp b/application/palemoon/components/feeds/nsFeedSniffer.cpp index 61cc77bdd..f314d3d3b 100644 --- a/application/palemoon/components/feeds/nsFeedSniffer.cpp +++ b/application/palemoon/components/feeds/nsFeedSniffer.cpp @@ -135,7 +135,7 @@ FindChar(char c, const char *begin, const char *end) * it's possible that someone embedded one of these tags inside a document of * another type, e.g. a HTML document, and we don't want to show the preview * page if the document isn't actually a feed. - * + * * @param start * The beginning of the data being sniffed * @param end @@ -331,7 +331,7 @@ nsFeedSniffer::OnStartRequest(nsIRequest* request, nsISupports* context) return NS_OK; } -NS_METHOD +nsresult nsFeedSniffer::AppendSegmentToString(nsIInputStream* inputStream, void* closure, const char* rawSegment, diff --git a/application/palemoon/components/feeds/nsFeedSniffer.h b/application/palemoon/components/feeds/nsFeedSniffer.h index 57e10d954..a0eb9862c 100644 --- a/application/palemoon/components/feeds/nsFeedSniffer.h +++ b/application/palemoon/components/feeds/nsFeedSniffer.h @@ -10,7 +10,7 @@ #include "mozilla/Attributes.h" class nsFeedSniffer final : public nsIContentSniffer, - nsIStreamListener + nsIStreamListener { public: NS_DECL_ISUPPORTS @@ -18,12 +18,12 @@ public: NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER - static NS_METHOD AppendSegmentToString(nsIInputStream* inputStream, - void* closure, - const char* rawSegment, - uint32_t toOffset, - uint32_t count, - uint32_t* writeCount); + static nsresult AppendSegmentToString(nsIInputStream* inputStream, + void* closure, + const char* rawSegment, + uint32_t toOffset, + uint32_t count, + uint32_t* writeCount); protected: ~nsFeedSniffer() {} diff --git a/application/palemoon/components/fuel/fuelApplication.js b/application/palemoon/components/fuel/fuelApplication.js index 89d568ae1..017813143 100644 --- a/application/palemoon/components/fuel/fuelApplication.js +++ b/application/palemoon/components/fuel/fuelApplication.js @@ -729,7 +729,7 @@ var ApplicationFactory = { }; -#include ../../../toolkit/components/exthelper/extApplication.js +#include ../../../../toolkit/components/exthelper/extApplication.js //================================================= // Application constructor diff --git a/application/palemoon/components/migration/nsIEHistoryEnumerator.cpp b/application/palemoon/components/migration/nsIEHistoryEnumerator.cpp index 7fe31a666..0b377d27e 100644 --- a/application/palemoon/components/migration/nsIEHistoryEnumerator.cpp +++ b/application/palemoon/components/migration/nsIEHistoryEnumerator.cpp @@ -1,139 +1,119 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIEHistoryEnumerator.h"
-
-#include <urlhist.h>
-#include <shlguid.h>
-
-#include "nsStringAPI.h"
-#include "nsNetUtil.h"
-#include "nsIVariant.h"
-#include "nsCOMArray.h"
-#include "nsArrayEnumerator.h"
-
-namespace {
-
- PRTime FileTimeToPRTime(FILETIME* filetime)
- {
- SYSTEMTIME st;
- ::FileTimeToSystemTime(filetime, &st);
- PRExplodedTime prt;
- prt.tm_year = st.wYear;
- // SYSTEMTIME's day-of-month parameter is 1-based,
- // PRExplodedTime's is 0-based.
- prt.tm_month = st.wMonth - 1;
- prt.tm_mday = st.wDay;
- prt.tm_hour = st.wHour;
- prt.tm_min = st.wMinute;
- prt.tm_sec = st.wSecond;
- prt.tm_usec = st.wMilliseconds * 1000;
- prt.tm_wday = 0;
- prt.tm_yday = 0;
- prt.tm_params.tp_gmt_offset = 0;
- prt.tm_params.tp_dst_offset = 0;
- return PR_ImplodeTime(&prt);
- }
-
-} // Anonymous namespace.
-
-////////////////////////////////////////////////////////////////////////////////
-//// nsIEHistoryEnumerator
-
-NS_IMPL_ISUPPORTS(nsIEHistoryEnumerator, nsISimpleEnumerator)
-
-nsIEHistoryEnumerator::nsIEHistoryEnumerator()
-{
- ::CoInitialize(nullptr);
-}
-
-nsIEHistoryEnumerator::~nsIEHistoryEnumerator()
-{
- ::CoUninitialize();
-}
-
-void
-nsIEHistoryEnumerator::EnsureInitialized()
-{
- if (mURLEnumerator)
- return;
-
- HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory,
- nullptr,
- CLSCTX_INPROC_SERVER,
- IID_IUrlHistoryStg2,
- getter_AddRefs(mIEHistory));
- if (FAILED(hr))
- return;
-
- hr = mIEHistory->EnumUrls(getter_AddRefs(mURLEnumerator));
- if (FAILED(hr))
- return;
-}
-
-NS_IMETHODIMP
-nsIEHistoryEnumerator::HasMoreElements(bool* _retval)
-{
- *_retval = false;
-
- EnsureInitialized();
- MOZ_ASSERT(mURLEnumerator, "Should have instanced an IE History URLEnumerator");
- if (!mURLEnumerator)
- return NS_OK;
-
- STATURL statURL;
- ULONG fetched;
-
- // First argument is not implemented, so doesn't matter what we pass.
- HRESULT hr = mURLEnumerator->Next(1, &statURL, &fetched);
- if (FAILED(hr) || fetched != 1UL) {
- // Reached the last entry.
- return NS_OK;
- }
-
- nsCOMPtr<nsIURI> uri;
- if (statURL.pwcsUrl) {
- nsDependentString url(statURL.pwcsUrl);
- nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
- ::CoTaskMemFree(statURL.pwcsUrl);
- if (NS_FAILED(rv)) {
- // Got a corrupt or invalid URI, continue to the next entry.
- return HasMoreElements(_retval);
- }
- }
-
- nsDependentString title(statURL.pwcsTitle);
-
- PRTime lastVisited = FileTimeToPRTime(&(statURL.ftLastVisited));
-
- mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1");
- MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag");
- if (mCachedNextEntry) {
- mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri);
- mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title);
- mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited);
-
- *_retval = true;
- }
-
- if (statURL.pwcsTitle)
- ::CoTaskMemFree(statURL.pwcsTitle);
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsIEHistoryEnumerator::GetNext(nsISupports** _retval)
-{
- *_retval = nullptr;
-
- if (!mCachedNextEntry)
- return NS_ERROR_FAILURE;
-
- NS_ADDREF(*_retval = mCachedNextEntry);
- // Release the cached entry, so it can't be returned twice.
- mCachedNextEntry = nullptr;
-
- return NS_OK;
-}
+/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIEHistoryEnumerator.h" + +#include <urlhist.h> +#include <shlguid.h> + +#include "nsArrayEnumerator.h" +#include "nsCOMArray.h" +#include "nsIVariant.h" +#include "nsNetUtil.h" +#include "nsStringAPI.h" +#include "nsWindowsMigrationUtils.h" +#include "prtime.h" + +//////////////////////////////////////////////////////////////////////////////// +//// nsIEHistoryEnumerator + +NS_IMPL_ISUPPORTS(nsIEHistoryEnumerator, nsISimpleEnumerator) + +nsIEHistoryEnumerator::nsIEHistoryEnumerator() +{ + ::CoInitialize(nullptr); +} + +nsIEHistoryEnumerator::~nsIEHistoryEnumerator() +{ + ::CoUninitialize(); +} + +void +nsIEHistoryEnumerator::EnsureInitialized() +{ + if (mURLEnumerator) + return; + + HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IUrlHistoryStg2, + getter_AddRefs(mIEHistory)); + if (FAILED(hr)) + return; + + hr = mIEHistory->EnumUrls(getter_AddRefs(mURLEnumerator)); + if (FAILED(hr)) + return; +} + +NS_IMETHODIMP +nsIEHistoryEnumerator::HasMoreElements(bool* _retval) +{ + *_retval = false; + + EnsureInitialized(); + MOZ_ASSERT(mURLEnumerator, "Should have instanced an IE History URLEnumerator"); + if (!mURLEnumerator) + return NS_OK; + + STATURL statURL; + ULONG fetched; + + // First argument is not implemented, so doesn't matter what we pass. + HRESULT hr = mURLEnumerator->Next(1, &statURL, &fetched); + if (FAILED(hr) || fetched != 1UL) { + // Reached the last entry. + return NS_OK; + } + + nsCOMPtr<nsIURI> uri; + if (statURL.pwcsUrl) { + nsDependentString url(statURL.pwcsUrl); + nsresult rv = NS_NewURI(getter_AddRefs(uri), url); + ::CoTaskMemFree(statURL.pwcsUrl); + if (NS_FAILED(rv)) { + // Got a corrupt or invalid URI, continue to the next entry. + return HasMoreElements(_retval); + } + } + + nsDependentString title(statURL.pwcsTitle ? statURL.pwcsTitle : L""); + + bool lastVisitTimeIsValid; + PRTime lastVisited = WinMigrationFileTimeToPRTime(&(statURL.ftLastVisited), &lastVisitTimeIsValid); + + mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1"); + MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag"); + if (mCachedNextEntry) { + mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri); + mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title); + if (lastVisitTimeIsValid) { + mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited); + } + + *_retval = true; + } + + if (statURL.pwcsTitle) + ::CoTaskMemFree(statURL.pwcsTitle); + + return NS_OK; +} + +NS_IMETHODIMP +nsIEHistoryEnumerator::GetNext(nsISupports** _retval) +{ + *_retval = nullptr; + + if (!mCachedNextEntry) + return NS_ERROR_FAILURE; + + NS_ADDREF(*_retval = mCachedNextEntry); + // Release the cached entry, so it can't be returned twice. + mCachedNextEntry = nullptr; + + return NS_OK; +} diff --git a/application/palemoon/components/migration/nsIEHistoryEnumerator.h b/application/palemoon/components/migration/nsIEHistoryEnumerator.h index fc1419859..1572a8dd5 100644 --- a/application/palemoon/components/migration/nsIEHistoryEnumerator.h +++ b/application/palemoon/components/migration/nsIEHistoryEnumerator.h @@ -1,37 +1,37 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef iehistoryenumerator___h___
-#define iehistoryenumerator___h___
-
-#include <urlhist.h>
-
-#include "mozilla/Attributes.h"
-#include "nsISimpleEnumerator.h"
-#include "nsIWritablePropertyBag2.h"
-#include "nsAutoPtr.h"
-
-class nsIEHistoryEnumerator final : public nsISimpleEnumerator
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSISIMPLEENUMERATOR
-
- nsIEHistoryEnumerator();
-
-private:
- ~nsIEHistoryEnumerator();
-
- /**
- * Initializes the history reader, if needed.
- */
- void EnsureInitialized();
-
- nsRefPtr<IUrlHistoryStg2> mIEHistory;
- nsRefPtr<IEnumSTATURL> mURLEnumerator;
-
- nsCOMPtr<nsIWritablePropertyBag2> mCachedNextEntry;
-};
-
-#endif
+/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef iehistoryenumerator___h___ +#define iehistoryenumerator___h___ + +#include <urlhist.h> + +#include "mozilla/Attributes.h" +#include "nsCOMPtr.h" +#include "nsISimpleEnumerator.h" +#include "nsIWritablePropertyBag2.h" + +class nsIEHistoryEnumerator final : public nsISimpleEnumerator +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISIMPLEENUMERATOR + + nsIEHistoryEnumerator(); + +private: + ~nsIEHistoryEnumerator(); + + /** + * Initializes the history reader, if needed. + */ + void EnsureInitialized(); + + RefPtr<IUrlHistoryStg2> mIEHistory; + RefPtr<IEnumSTATURL> mURLEnumerator; + + nsCOMPtr<nsIWritablePropertyBag2> mCachedNextEntry; +}; + +#endif diff --git a/application/palemoon/components/migration/nsWindowsMigrationUtils.h b/application/palemoon/components/migration/nsWindowsMigrationUtils.h new file mode 100644 index 000000000..0288d93d3 --- /dev/null +++ b/application/palemoon/components/migration/nsWindowsMigrationUtils.h @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef windowsmigrationutils__h__ +#define windowsmigrationutils__h__ + +#include "prtime.h" + +static +PRTime WinMigrationFileTimeToPRTime(FILETIME* filetime, bool* isValid) +{ + SYSTEMTIME st; + *isValid = ::FileTimeToSystemTime(filetime, &st); + if (!*isValid) { + return 0; + } + PRExplodedTime prt; + prt.tm_year = st.wYear; + // SYSTEMTIME's day-of-month parameter is 1-based, + // PRExplodedTime's is 0-based. + prt.tm_month = st.wMonth - 1; + prt.tm_mday = st.wDay; + prt.tm_hour = st.wHour; + prt.tm_min = st.wMinute; + prt.tm_sec = st.wSecond; + prt.tm_usec = st.wMilliseconds * 1000; + prt.tm_wday = 0; + prt.tm_yday = 0; + prt.tm_params.tp_gmt_offset = 0; + prt.tm_params.tp_dst_offset = 0; + return PR_ImplodeTime(&prt); +} + +#endif + diff --git a/application/palemoon/components/nsBrowserGlue.js b/application/palemoon/components/nsBrowserGlue.js index 705593b59..8fc24c7d3 100644 --- a/application/palemoon/components/nsBrowserGlue.js +++ b/application/palemoon/components/nsBrowserGlue.js @@ -1213,7 +1213,7 @@ BrowserGlue.prototype = { }, _migrateUI: function BG__migrateUI() { - const UI_VERSION = 14; + const UI_VERSION = 15; const BROWSER_DOCURL = "chrome://browser/content/browser.xul#"; let currentUIVersion = 0; try { @@ -1395,7 +1395,7 @@ BrowserGlue.prototype = { } } - if (currentUIVersion < 14) { + if (currentUIVersion < 16) { // Migrate Sync from pmsync.palemoon.net to pmsync.palemoon.org try { let syncURL = Services.prefs.getCharPref("services.sync.clusterURL"); diff --git a/application/palemoon/components/sessionstore/nsSessionStartup.js b/application/palemoon/components/sessionstore/nsSessionStartup.js index 024246619..7f07e9050 100644 --- a/application/palemoon/components/sessionstore/nsSessionStartup.js +++ b/application/palemoon/components/sessionstore/nsSessionStartup.js @@ -77,9 +77,14 @@ SessionStartup.prototype = { return; } - _SessionFile.read().then( - this._onSessionFileRead.bind(this) - ); + if (Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") || + Services.prefs.getIntPref("browser.startup.page") == 3) { + this._ensureInitialized(); + } else { + _SessionFile.read().then( + this._onSessionFileRead.bind(this) + ); + } }, // Wrap a string as a nsISupports diff --git a/application/palemoon/components/shell/Makefile.in b/application/palemoon/components/shell/Makefile.in deleted file mode 100644 index df084b709..000000000 --- a/application/palemoon/components/shell/Makefile.in +++ /dev/null @@ -1,11 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -include $(topsrcdir)/config/rules.mk - -CXXFLAGS += $(TK_CFLAGS) - -clobber:: - rm -f $(DIST)/lib/$(LIBRARY_NAME).lib diff --git a/application/palemoon/components/shell/ShellService.jsm b/application/palemoon/components/shell/ShellService.jsm new file mode 100644 index 000000000..12e275bdb --- /dev/null +++ b/application/palemoon/components/shell/ShellService.jsm @@ -0,0 +1,114 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this file, +* You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +this.EXPORTED_SYMBOLS = ["ShellService"]; + +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; + +Cu.import("resource://gre/modules/AppConstants.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry", + "resource://gre/modules/WindowsRegistry.jsm"); + +/** + * Internal functionality to save and restore the docShell.allow* properties. + */ +let ShellServiceInternal = { + /** + * Used to determine whether or not to offer "Set as desktop background" + * functionality. Even if shell service is available it is not + * guaranteed that it is able to set the background for every desktop + * which is especially true for Linux with its many different desktop + * environments. + */ + get canSetDesktopBackground() { + if (AppConstants.platform == "win" || + AppConstants.platform == "macosx") { + return true; + } + + if (AppConstants.platform == "linux") { + if (this.shellService) { + let linuxShellService = this.shellService + .QueryInterface(Ci.nsIGNOMEShellService); + return linuxShellService.canSetDesktopBackground; + } + } + + return false; + }, + + /** + * Used to determine whether or not to show a "Set Default Browser" + * query dialog. This attribute is true if the application is starting + * up and "browser.shell.checkDefaultBrowser" is true, otherwise it + * is false. + */ + _checkedThisSession: false, + get shouldCheckDefaultBrowser() { + // If we've already checked, the browser has been started and this is a + // new window open, and we don't want to check again. + if (this._checkedThisSession) { + return false; + } + + if (!Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser")) { + return false; + } + + if (AppConstants.platform == "win") { + let optOutValue = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "Software\\Mozilla\\PaleMoon", + "DefaultBrowserOptOut"); + WindowsRegistry.removeRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "Software\\Mozilla\\PaleMoon", + "DefaultBrowserOptOut"); + if (optOutValue == "True") { + Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", false); + return false; + } + } + + return true; + }, + + set shouldCheckDefaultBrowser(shouldCheck) { + Services.prefs.setBoolPref("browser.shell.checkDefaultBrowser", !!shouldCheck); + }, + + isDefaultBrowser(startupCheck, forAllTypes) { + // If this is the first browser window, maintain internal state that we've + // checked this session (so that subsequent window opens don't show the + // default browser dialog). + if (startupCheck) { + this._checkedThisSession = true; + } + if (this.shellService) { + return this.shellService.isDefaultBrowser(startupCheck, forAllTypes); + } + return false; + } +}; + +XPCOMUtils.defineLazyServiceGetter(ShellServiceInternal, "shellService", + "@mozilla.org/browser/shell-service;1", Ci.nsIShellService); + +/** + * The external API exported by this module. + */ +this.ShellService = new Proxy(ShellServiceInternal, { + get(target, name) { + if (name in target) { + return target[name]; + } + if (target.shellService) { + return target.shellService[name]; + } + Services.console.logStringMessage(`${name} not found in ShellService: ${target.shellService}`); + return undefined; + } +}); diff --git a/application/palemoon/components/shell/content/setDesktopBackground.js b/application/palemoon/components/shell/content/setDesktopBackground.js index e90a32d03..53cc70db0 100644 --- a/application/palemoon/components/shell/content/setDesktopBackground.js +++ b/application/palemoon/components/shell/content/setDesktopBackground.js @@ -1,16 +1,14 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Components.utils.import("resource://gre/modules/AppConstants.jsm"); var Ci = Components.interfaces; var gSetBackground = { -#ifndef XP_MACOSX - _position : "", - _backgroundColor : 0, -#else - _position : "STRETCH", -#endif + _position : AppConstants.platform == "macosx" ? "STRETCH" : "", + _backgroundColor : AppConstants.platform != "macosx" ? 0 : undefined, _screenWidth : 0, _screenHeight : 0, _image : null, @@ -27,23 +25,23 @@ var gSetBackground = { this._canvas = document.getElementById("screen"); this._screenWidth = screen.width; this._screenHeight = screen.height; -#ifdef XP_MACOSX - document.documentElement.getButton("accept").hidden = true; -#endif + if (AppConstants.platform == "macosx") { + document.documentElement.getButton("accept").hidden = true; + } if (this._screenWidth / this._screenHeight >= 1.6) document.getElementById("monitor").setAttribute("aspectratio", "16:10"); -#ifdef XP_WIN - // hide fill + fit options if <win7 since don't work - var version = Components.classes["@mozilla.org/system-info;1"] - .getService(Ci.nsIPropertyBag2) - .getProperty("version"); - var isWindows7OrHigher = (parseFloat(version) >= 6.1); - if (!isWindows7OrHigher) { - document.getElementById("fillPosition").hidden = true; - document.getElementById("fitPosition").hidden = true; + if (AppConstants.platform == "win") { + // Hide fill + fit options if < Win7 since they don't work. + var version = Components.classes["@mozilla.org/system-info;1"] + .getService(Ci.nsIPropertyBag2) + .getProperty("version"); + var isWindows7OrHigher = (parseFloat(version) >= 6.1); + if (!isWindows7OrHigher) { + document.getElementById("fillPosition").hidden = true; + document.getElementById("fitPosition").hidden = true; + } } -#endif // make sure that the correct dimensions will be used setTimeout(function(self) { @@ -62,92 +60,37 @@ var gSetBackground = { var ctx = this._canvas.getContext("2d"); ctx.scale(this._canvas.clientWidth / this._screenWidth, this._canvas.clientHeight / this._screenHeight); -#ifndef XP_MACOSX - this._initColor(); -#else - // Make sure to reset the button state in case the user has already - // set an image as their desktop background. - var setDesktopBackground = document.getElementById("setDesktopBackground"); - setDesktopBackground.hidden = false; - var bundle = document.getElementById("backgroundBundle"); - setDesktopBackground.label = bundle.getString("DesktopBackgroundSet"); - setDesktopBackground.disabled = false; - - document.getElementById("showDesktopPreferences").hidden = true; -#endif + if (AppConstants.platform != "macosx") { + this._initColor(); + } else { + // Make sure to reset the button state in case the user has already + // set an image as their desktop background. + var setDesktopBackground = document.getElementById("setDesktopBackground"); + setDesktopBackground.hidden = false; + var bundle = document.getElementById("backgroundBundle"); + setDesktopBackground.label = bundle.getString("DesktopBackgroundSet"); + setDesktopBackground.disabled = false; + + document.getElementById("showDesktopPreferences").hidden = true; + } this.updatePosition(); }, -#ifndef XP_MACOSX - _initColor: function () - { - var color = this._shell.desktopBackgroundColor; - - const rMask = 4294901760; - const gMask = 65280; - const bMask = 255; - var r = (color & rMask) >> 16; - var g = (color & gMask) >> 8; - var b = (color & bMask); - this.updateColor(this._rgbToHex(r, g, b)); - - var colorpicker = document.getElementById("desktopColor"); - colorpicker.color = this._backgroundColor; - }, - - updateColor: function (aColor) - { - this._backgroundColor = aColor; - this._canvas.style.backgroundColor = aColor; - }, - - // Converts a color string in the format "#RRGGBB" to an integer. - _hexStringToLong: function (aString) - { - return parseInt(aString.substring(1,3), 16) << 16 | - parseInt(aString.substring(3,5), 16) << 8 | - parseInt(aString.substring(5,7), 16); - }, - - _rgbToHex: function (aR, aG, aB) - { - return "#" + [aR, aG, aB].map(function(aInt) aInt.toString(16).replace(/^(.)$/, "0$1")) - .join("").toUpperCase(); - }, -#else - observe: function (aSubject, aTopic, aData) + setDesktopBackground: function () { - if (aTopic == "shell:desktop-background-changed") { - document.getElementById("setDesktopBackground").hidden = true; - document.getElementById("showDesktopPreferences").hidden = false; - + if (AppConstants.platform != "macosx") { + document.persist("menuPosition", "value"); + this._shell.desktopBackgroundColor = this._hexStringToLong(this._backgroundColor); + } else { Components.classes["@mozilla.org/observer-service;1"] .getService(Ci.nsIObserverService) - .removeObserver(this, "shell:desktop-background-changed"); - } - }, - - showDesktopPrefs: function() - { - this._shell.openApplication(Ci.nsIMacShellService.APPLICATION_DESKTOP); - }, -#endif + .addObserver(this, "shell:desktop-background-changed", false); - setDesktopBackground: function () - { -#ifndef XP_MACOSX - document.persist("menuPosition", "value"); - this._shell.desktopBackgroundColor = this._hexStringToLong(this._backgroundColor); -#else - Components.classes["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService) - .addObserver(this, "shell:desktop-background-changed", false); - - var bundle = document.getElementById("backgroundBundle"); - var setDesktopBackground = document.getElementById("setDesktopBackground"); - setDesktopBackground.disabled = true; - setDesktopBackground.label = bundle.getString("DesktopBackgroundDownloading"); -#endif + var bundle = document.getElementById("backgroundBundle"); + var setDesktopBackground = document.getElementById("setDesktopBackground"); + setDesktopBackground.disabled = true; + setDesktopBackground.label = bundle.getString("DesktopBackgroundDownloading"); + } this._shell.setDesktopBackground(this._image, Ci.nsIShellService["BACKGROUND_" + this._position]); }, @@ -157,9 +100,9 @@ var gSetBackground = { var ctx = this._canvas.getContext("2d"); ctx.clearRect(0, 0, this._screenWidth, this._screenHeight); -#ifndef XP_MACOSX - this._position = document.getElementById("menuPosition").value; -#endif + if (AppConstants.platform != "macosx") { + this._position = document.getElementById("menuPosition").value; + } switch (this._position) { case "TILE": @@ -171,43 +114,101 @@ var gSetBackground = { case "STRETCH": ctx.drawImage(this._image, 0, 0, this._screenWidth, this._screenHeight); break; - case "CENTER": - var x = (this._screenWidth - this._image.naturalWidth) / 2; - var y = (this._screenHeight - this._image.naturalHeight) / 2; + case "CENTER": { + let x = (this._screenWidth - this._image.naturalWidth) / 2; + let y = (this._screenHeight - this._image.naturalHeight) / 2; ctx.drawImage(this._image, x, y); break; - case "FILL": - //Try maxing width first, overflow height - var widthRatio = this._screenWidth / this._image.naturalWidth; - var width = this._image.naturalWidth * widthRatio; - var height = this._image.naturalHeight * widthRatio; + } + case "FILL": { + // Try maxing width first, overflow height. + let widthRatio = this._screenWidth / this._image.naturalWidth; + let width = this._image.naturalWidth * widthRatio; + let height = this._image.naturalHeight * widthRatio; if (height < this._screenHeight) { - //height less than screen, max height and overflow width - var heightRatio = this._screenHeight / this._image.naturalHeight; + // Height less than screen, max height and overflow width. + let heightRatio = this._screenHeight / this._image.naturalHeight; width = this._image.naturalWidth * heightRatio; height = this._image.naturalHeight * heightRatio; } - var x = (this._screenWidth - width) / 2; - var y = (this._screenHeight - height) / 2; + let x = (this._screenWidth - width) / 2; + let y = (this._screenHeight - height) / 2; ctx.drawImage(this._image, x, y, width, height); break; - case "FIT": - //Try maxing width first, top and bottom borders - var widthRatio = this._screenWidth / this._image.naturalWidth; - var width = this._image.naturalWidth * widthRatio; - var height = this._image.naturalHeight * widthRatio; - var x = 0; - var y = (this._screenHeight - height) / 2; + } + case "FIT": { + // Try maxing width first, top and bottom borders. + let widthRatio = this._screenWidth / this._image.naturalWidth; + let width = this._image.naturalWidth * widthRatio; + let height = this._image.naturalHeight * widthRatio; + let x = 0; + let y = (this._screenHeight - height) / 2; if (height > this._screenHeight) { - //height overflow, maximise height, side borders - var heightRatio = this._screenHeight / this._image.naturalHeight; + // Height overflow, maximise height, side borders. + let heightRatio = this._screenHeight / this._image.naturalHeight; width = this._image.naturalWidth * heightRatio; height = this._image.naturalHeight * heightRatio; x = (this._screenWidth - width) / 2; y = 0; } ctx.drawImage(this._image, x, y, width, height); - break; + break; + } } } }; + +if (AppConstants.platform != "macosx") { + gSetBackground["_initColor"] = function () + { + var color = this._shell.desktopBackgroundColor; + + const rMask = 4294901760; + const gMask = 65280; + const bMask = 255; + var r = (color & rMask) >> 16; + var g = (color & gMask) >> 8; + var b = (color & bMask); + this.updateColor(this._rgbToHex(r, g, b)); + + var colorpicker = document.getElementById("desktopColor"); + colorpicker.color = this._backgroundColor; + }; + + gSetBackground["updateColor"] = function (aColor) + { + this._backgroundColor = aColor; + this._canvas.style.backgroundColor = aColor; + }; + + // Converts a color string in the format "#RRGGBB" to an integer. + gSetBackground["_hexStringToLong"] = function (aString) + { + return parseInt(aString.substring(1, 3), 16) << 16 | + parseInt(aString.substring(3, 5), 16) << 8 | + parseInt(aString.substring(5, 7), 16); + }; + + gSetBackground["_rgbToHex"] = function (aR, aG, aB) + { + return "#" + [aR, aG, aB].map(aInt => aInt.toString(16).replace(/^(.)$/, "0$1")) + .join("").toUpperCase(); + }; +} else { + gSetBackground["observe"] = function (aSubject, aTopic, aData) + { + if (aTopic == "shell:desktop-background-changed") { + document.getElementById("setDesktopBackground").hidden = true; + document.getElementById("showDesktopPreferences").hidden = false; + + Components.classes["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService) + .removeObserver(this, "shell:desktop-background-changed"); + } + }; + + gSetBackground["showDesktopPrefs"] = function() + { + this._shell.openApplication(Ci.nsIMacShellService.APPLICATION_DESKTOP); + }; +} diff --git a/application/palemoon/components/shell/jar.mn b/application/palemoon/components/shell/jar.mn index eed15c397..1f33b5d56 100644 --- a/application/palemoon/components/shell/jar.mn +++ b/application/palemoon/components/shell/jar.mn @@ -4,4 +4,4 @@ browser.jar: * content/browser/setDesktopBackground.xul (content/setDesktopBackground.xul) -* content/browser/setDesktopBackground.js (content/setDesktopBackground.js) + content/browser/setDesktopBackground.js (content/setDesktopBackground.js) diff --git a/application/palemoon/components/shell/moz.build b/application/palemoon/components/shell/moz.build index 38965c5d7..94ec88571 100644 --- a/application/palemoon/components/shell/moz.build +++ b/application/palemoon/components/shell/moz.build @@ -1,4 +1,4 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -18,6 +18,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': XPIDL_SOURCES += [ 'nsIMacShellService.idl', ] +elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + XPIDL_SOURCES += [ + 'nsIGNOMEShellService.idl', + ] XPIDL_MODULE = 'shellservice' @@ -29,7 +33,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': SOURCES += [ 'nsMacShellService.cpp', ] -elif CONFIG['MOZ_WIDGET_GTK']: +elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: SOURCES += [ 'nsGNOMEShellService.cpp', ] @@ -42,6 +46,10 @@ EXTRA_COMPONENTS += [ 'nsSetDefaultBrowser.manifest', ] +EXTRA_JS_MODULES += [ + 'ShellService.jsm', +] + for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION'): DEFINES[var] = '"%s"' % CONFIG[var] diff --git a/application/palemoon/components/shell/nsGNOMEShellService.cpp b/application/palemoon/components/shell/nsGNOMEShellService.cpp index 14510d111..9bc5f5913 100644 --- a/application/palemoon/components/shell/nsGNOMEShellService.cpp +++ b/application/palemoon/components/shell/nsGNOMEShellService.cpp @@ -21,12 +21,13 @@ #include "nsIStringBundle.h" #include "nsIOutputStream.h" #include "nsIProcess.h" -#include "nsNetUtil.h" +#include "nsServiceManagerUtils.h" +#include "nsComponentManagerUtils.h" #include "nsIDOMHTMLImageElement.h" #include "nsIImageLoadingContent.h" #include "imgIRequest.h" #include "imgIContainer.h" -#include "prprf.h" +#include "mozilla/Sprintf.h" #if defined(MOZ_WIDGET_GTK) #include "nsIImageToPixbuf.h" #endif @@ -116,7 +117,7 @@ nsGNOMEShellService::Init() return appPath->GetNativePath(mAppPath); } -NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIShellService) +NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIGNOMEShellService, nsIShellService) bool nsGNOMEShellService::GetAppPathFromLauncher() @@ -152,7 +153,8 @@ nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const gchar *commandPath; if (mUseLocaleFilenames) { - gchar *nativePath = g_filename_from_utf8(aKeyValue, -1, nullptr, nullptr, nullptr); + gchar *nativePath = g_filename_from_utf8(aKeyValue, -1, + nullptr, nullptr, nullptr); if (!nativePath) { NS_ERROR("Error converting path to filesystem encoding"); return false; @@ -199,8 +201,6 @@ nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck, bool* aIsDefaultBrowser) { *aIsDefaultBrowser = false; - if (aStartupCheck) - mCheckedThisSession = true; nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID); nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); @@ -284,7 +284,7 @@ nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes, NS_ENSURE_SUCCESS(rv, rv); nsString brandShortName; - brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"), + brandBundle->GetStringFromName(u"brandShortName", getter_Copies(brandShortName)); // use brandShortName as the application id. @@ -312,41 +312,14 @@ nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes, } } - return NS_OK; -} - -NS_IMETHODIMP -nsGNOMEShellService::GetShouldCheckDefaultBrowser(bool* aResult) -{ - // If we've already checked, the browser has been started and this is a - // new window open, and we don't want to check again. - if (mCheckedThisSession) { - *aResult = false; - return NS_OK; + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true); + // Reset the number of times the dialog should be shown + // before it is silenced. + (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0); } - nsCOMPtr<nsIPrefBranch> prefs; - nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (pserve) - pserve->GetBranch("", getter_AddRefs(prefs)); - - if (prefs) - prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult); - - return NS_OK; -} - -NS_IMETHODIMP -nsGNOMEShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck) -{ - nsCOMPtr<nsIPrefBranch> prefs; - nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (pserve) - pserve->GetBranch("", getter_AddRefs(prefs)); - - if (prefs) - prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck); - return NS_OK; } @@ -386,7 +359,7 @@ WriteImage(const nsCString& aPath, imgIContainer* aImage) return res ? NS_OK : NS_ERROR_FAILURE; #endif } - + NS_IMETHODIMP nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, int32_t aPosition) @@ -407,15 +380,15 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, // Set desktop wallpaper filling style nsAutoCString options; if (aPosition == BACKGROUND_TILE) - options.Assign("wallpaper"); + options.AssignLiteral("wallpaper"); else if (aPosition == BACKGROUND_STRETCH) - options.Assign("stretched"); + options.AssignLiteral("stretched"); else if (aPosition == BACKGROUND_FILL) - options.Assign("zoom"); + options.AssignLiteral("zoom"); else if (aPosition == BACKGROUND_FIT) - options.Assign("scaled"); + options.AssignLiteral("scaled"); else - options.Assign("centered"); + options.AssignLiteral("centered"); // Write the background file to the home directory. nsAutoCString filePath(PR_GetEnv("HOME")); @@ -429,7 +402,7 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, rv = bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle)); if (NS_SUCCEEDED(rv) && brandBundle) { - rv = brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"), + rv = brandBundle->GetStringFromName(u"brandShortName", getter_Copies(brandName)); NS_ENSURE_SUCCESS(rv, rv); } @@ -438,7 +411,7 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, // build the file name filePath.Append('/'); filePath.Append(NS_ConvertUTF16toUTF8(brandName)); - filePath.Append("_wallpaper.png"); + filePath.AppendLiteral("_wallpaper.png"); // write the image to a file in the home dir rv = WriteImage(filePath, container); @@ -478,7 +451,7 @@ nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement, // Set the image to an empty string first to force a refresh // (since we could be writing a new image on top of an existing - // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes) + // PaleMoon_wallpaper.png and nautilus doesn't monitor the file for changes) gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), EmptyCString()); @@ -543,7 +516,7 @@ ColorToCString(uint32_t aColor, nsCString& aResult) uint16_t green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff); uint16_t blue = COLOR_8_TO_16_BIT(aColor & 0xff); - PR_snprintf(buf, 14, "#%04x%04x%04x", red, green, blue); + snprintf(buf, 14, "#%04x%04x%04x", red, green, blue); } NS_IMETHODIMP @@ -580,9 +553,9 @@ nsGNOMEShellService::OpenApplication(int32_t aApplication) { nsAutoCString scheme; if (aApplication == APPLICATION_MAIL) - scheme.Assign("mailto"); + scheme.AssignLiteral("mailto"); else if (aApplication == APPLICATION_NEWS) - scheme.Assign("news"); + scheme.AssignLiteral("news"); else return NS_ERROR_NOT_AVAILABLE; diff --git a/application/palemoon/components/shell/nsGNOMEShellService.h b/application/palemoon/components/shell/nsGNOMEShellService.h index 36a4a0c42..a7b003802 100644 --- a/application/palemoon/components/shell/nsGNOMEShellService.h +++ b/application/palemoon/components/shell/nsGNOMEShellService.h @@ -6,28 +6,28 @@ #ifndef nsgnomeshellservice_h____ #define nsgnomeshellservice_h____ -#include "nsIShellService.h" +#include "nsIGNOMEShellService.h" #include "nsStringAPI.h" #include "mozilla/Attributes.h" -class nsGNOMEShellService final : public nsIShellService +class nsGNOMEShellService final : public nsIGNOMEShellService { public: - nsGNOMEShellService() : mCheckedThisSession(false), mAppIsInPath(false) { } + nsGNOMEShellService() : mAppIsInPath(false) { } NS_DECL_ISUPPORTS NS_DECL_NSISHELLSERVICE + NS_DECL_NSIGNOMESHELLSERVICE - nsresult Init() NS_HIDDEN; + nsresult Init(); private: ~nsGNOMEShellService() {} - NS_HIDDEN_(bool) KeyMatchesAppName(const char *aKeyValue) const; - NS_HIDDEN_(bool) CheckHandlerMatchesAppName(const nsACString& handler) const; + bool KeyMatchesAppName(const char *aKeyValue) const; + bool CheckHandlerMatchesAppName(const nsACString& handler) const; - NS_HIDDEN_(bool) GetAppPathFromLauncher(); - bool mCheckedThisSession; + bool GetAppPathFromLauncher(); bool mUseLocaleFilenames; nsCString mAppPath; bool mAppIsInPath; diff --git a/application/palemoon/components/shell/nsIGNOMEShellService.idl b/application/palemoon/components/shell/nsIGNOMEShellService.idl new file mode 100644 index 000000000..842ce5e8a --- /dev/null +++ b/application/palemoon/components/shell/nsIGNOMEShellService.idl @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIShellService.idl" + +[scriptable, uuid(2ce5c803-edcd-443d-98eb-ceba86d02d13)] +interface nsIGNOMEShellService : nsIShellService +{ + /** + * Used to determine whether or not to offer "Set as desktop background" + * functionality. Even if shell service is available it is not + * guaranteed that it is able to set the background for every desktop + * which is especially true for Linux with its many different desktop + * environments. + */ + readonly attribute boolean canSetDesktopBackground; +}; + diff --git a/application/palemoon/components/shell/nsIMacShellService.idl b/application/palemoon/components/shell/nsIMacShellService.idl index 3c2f42315..6a532bbd0 100644 --- a/application/palemoon/components/shell/nsIMacShellService.idl +++ b/application/palemoon/components/shell/nsIMacShellService.idl @@ -5,7 +5,7 @@ #include "nsIShellService.idl" -[scriptable, uuid(7f8ca08e-1df4-4735-86e9-50dedb48e5e8)] +[scriptable, uuid(387fdc80-0077-4b60-a0d9-d9e80a83ba64)] interface nsIMacShellService : nsIShellService { const long APPLICATION_KEYCHAIN_ACCESS = 2; diff --git a/application/palemoon/components/shell/nsIShellService.idl b/application/palemoon/components/shell/nsIShellService.idl index 4825741b3..3e7e94b00 100644 --- a/application/palemoon/components/shell/nsIShellService.idl +++ b/application/palemoon/components/shell/nsIShellService.idl @@ -8,7 +8,7 @@ interface nsIDOMElement; interface nsIFile; -[scriptable, uuid(99d2e9f1-3c86-40f7-81fd-3060c18489f0)] +[scriptable, uuid(2d1a95e4-5bd8-4eeb-b0a8-c1455fd2a357)] interface nsIShellService : nsISupports { /** @@ -39,23 +39,6 @@ interface nsIShellService : nsISupports void setDefaultBrowser(in boolean aClaimAllTypes, in boolean aForAllUsers); /** - * Used to determine whether or not to show a "Set Default Browser" - * query dialog. This attribute is true if the application is starting - * up and "browser.shell.checkDefaultBrowser" is true, otherwise it - * is false. - */ - attribute boolean shouldCheckDefaultBrowser; - - /** - * Used to determine whether or not to offer "Set as desktop background" - * functionality. Even if shell service is available it is not - * guaranteed that it is able to set the background for every desktop - * which is especially true for Linux with its many different desktop - * environments. - */ - readonly attribute boolean canSetDesktopBackground; - - /** * Flags for positioning/sizing of the Desktop Background image. */ const long BACKGROUND_TILE = 1; diff --git a/application/palemoon/components/shell/nsIWindowsShellService.idl b/application/palemoon/components/shell/nsIWindowsShellService.idl index 913eb4292..57ed37055 100644 --- a/application/palemoon/components/shell/nsIWindowsShellService.idl +++ b/application/palemoon/components/shell/nsIWindowsShellService.idl @@ -5,7 +5,7 @@ #include "nsIShellService.idl" -[scriptable, uuid(89b0a761-d9a0-4c39-ab83-d81566459a31)] +[scriptable, uuid(f8a26b94-49e5-4441-8fbc-315e0b4f22ef)] interface nsIWindowsShellService : nsIShellService { /** diff --git a/application/palemoon/components/shell/nsMacShellService.cpp b/application/palemoon/components/shell/nsMacShellService.cpp index 914b9ae65..d8d64039d 100644 --- a/application/palemoon/components/shell/nsMacShellService.cpp +++ b/application/palemoon/components/shell/nsMacShellService.cpp @@ -17,13 +17,13 @@ #include "nsIURL.h" #include "nsIWebBrowserPersist.h" #include "nsMacShellService.h" -#include "nsNetUtil.h" +#include "nsIProperties.h" +#include "nsServiceManagerUtils.h" #include "nsShellService.h" #include "nsStringAPI.h" #include "nsIDocShell.h" #include "nsILoadContext.h" - #include <CoreFoundation/CoreFoundation.h> #include <ApplicationServices/ApplicationServices.h> @@ -49,19 +49,14 @@ nsMacShellService::IsDefaultBrowser(bool aStartupCheck, return NS_ERROR_FAILURE; } - // Get the default http handler's bundle ID (or nullptr if it has not been explicitly set) + // Get the default http handler's bundle ID (or nullptr if it has not been + // explicitly set) CFStringRef defaultBrowserID = ::LSCopyDefaultHandlerForURLScheme(CFSTR("http")); if (defaultBrowserID) { *aIsDefaultBrowser = ::CFStringCompare(firefoxID, defaultBrowserID, 0) == kCFCompareEqualTo; ::CFRelease(defaultBrowserID); } - // If this is the first browser window, maintain internal state that we've - // checked this session (so that subsequent window opens don't show the - // default browser dialog). - if (aStartupCheck) - mCheckedThisSession = true; - return NS_OK; } @@ -90,47 +85,15 @@ nsMacShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers) return NS_ERROR_FAILURE; } } - - return NS_OK; -} -NS_IMETHODIMP -nsMacShellService::GetShouldCheckDefaultBrowser(bool* aResult) -{ - // If we've already checked, the browser has been started and this is a - // new window open, and we don't want to check again. - if (mCheckedThisSession) { - *aResult = false; - return NS_OK; + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true); + // Reset the number of times the dialog should be shown + // before it is silenced. + (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0); } - nsCOMPtr<nsIPrefBranch> prefs; - nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (pserve) - pserve->GetBranch("", getter_AddRefs(prefs)); - - prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult); - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck) -{ - nsCOMPtr<nsIPrefBranch> prefs; - nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID)); - if (pserve) - pserve->GetBranch("", getter_AddRefs(prefs)); - - prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck); - - return NS_OK; -} - -NS_IMETHODIMP -nsMacShellService::GetCanSetDesktopBackground(bool* aResult) -{ - *aResult = true; return NS_OK; } @@ -202,8 +165,10 @@ nsMacShellService::SetDesktopBackground(nsIDOMElement* aElement, loadContext = do_QueryInterface(docShell); } - return wbp->SaveURI(imageURI, nullptr, docURI, content->OwnerDoc()->GetReferrerPolicy(), - nullptr, nullptr, mBackgroundFile, loadContext); + return wbp->SaveURI(imageURI, nullptr, + docURI, content->OwnerDoc()->GetReferrerPolicy(), + nullptr, nullptr, + mBackgroundFile, loadContext); } NS_IMETHODIMP @@ -269,7 +234,8 @@ nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress, OSStatus status; // Convert the path into a FSRef - status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef, nullptr); + status = ::FSPathMakeRef((const UInt8*)nativePath.get(), &pictureRef, + nullptr); if (status == noErr) { err = ::FSNewAlias(nil, &pictureRef, &aliasHandle); if (err == noErr && aliasHandle == nil) @@ -336,8 +302,8 @@ nsMacShellService::OpenApplication(int32_t aApplication) } break; case nsIMacShellService::APPLICATION_KEYCHAIN_ACCESS: - err = ::LSGetApplicationForInfo('APPL', 'kcmr', nullptr, kLSRolesAll, nullptr, - &appURL); + err = ::LSGetApplicationForInfo('APPL', 'kcmr', nullptr, kLSRolesAll, + nullptr, &appURL); break; case nsIMacShellService::APPLICATION_NETWORK: { @@ -349,8 +315,7 @@ nsMacShellService::OpenApplication(int32_t aApplication) if (!exists) return NS_ERROR_FILE_NOT_FOUND; return lf->Launch(); - } - break; + } case nsIMacShellService::APPLICATION_DESKTOP: { nsCOMPtr<nsIFile> lf; @@ -361,8 +326,7 @@ nsMacShellService::OpenApplication(int32_t aApplication) if (!exists) return NS_ERROR_FILE_NOT_FOUND; return lf->Launch(); - } - break; + } } if (appURL && err == noErr) { diff --git a/application/palemoon/components/shell/nsMacShellService.h b/application/palemoon/components/shell/nsMacShellService.h index 7ca1c71ac..db9527809 100644 --- a/application/palemoon/components/shell/nsMacShellService.h +++ b/application/palemoon/components/shell/nsMacShellService.h @@ -15,7 +15,7 @@ class nsMacShellService : public nsIMacShellService, public nsIWebProgressListener { public: - nsMacShellService() : mCheckedThisSession(false) {}; + nsMacShellService() {}; NS_DECL_ISUPPORTS NS_DECL_NSISHELLSERVICE @@ -27,8 +27,6 @@ protected: private: nsCOMPtr<nsIFile> mBackgroundFile; - - bool mCheckedThisSession; }; #endif // nsmacshellservice_h____ diff --git a/application/palemoon/components/shell/nsSetDefaultBrowser.js b/application/palemoon/components/shell/nsSetDefaultBrowser.js index d1d1e72cb..c7a78c538 100644 --- a/application/palemoon/components/shell/nsSetDefaultBrowser.js +++ b/application/palemoon/components/shell/nsSetDefaultBrowser.js @@ -2,13 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* - * -setDefaultBrowser commandline handler +/* + * --setDefaultBrowser commandline handler * Makes the current executable the "default browser". */ const Cc = Components.classes; const Ci = Components.interfaces; +Components.utils.import("resource:///modules/ShellService.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); function nsSetDefaultBrowser() {} @@ -16,13 +17,11 @@ function nsSetDefaultBrowser() {} nsSetDefaultBrowser.prototype = { handle: function nsSetDefault_handle(aCmdline) { if (aCmdline.handleFlag("setDefaultBrowser", false)) { - var shell = Cc["@mozilla.org/browser/shell-service;1"]. - getService(Ci.nsIShellService); - shell.setDefaultBrowser(true, true); + ShellService.setDefaultBrowser(true, true); } }, - helpInfo: " -setDefaultBrowser Set this app as the default browser.\n", + helpInfo: " --setDefaultBrowser Set this app as the default browser.\n", classID: Components.ID("{F57899D0-4E2C-4ac6-9E29-50C736103B0C}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]), diff --git a/application/palemoon/components/shell/nsShellService.h b/application/palemoon/components/shell/nsShellService.h index d5fade37b..516a8423a 100644 --- a/application/palemoon/components/shell/nsShellService.h +++ b/application/palemoon/components/shell/nsShellService.h @@ -4,6 +4,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #define PREF_CHECKDEFAULTBROWSER "browser.shell.checkDefaultBrowser" +#define PREF_SKIPDEFAULTBROWSERCHECK "browser.shell.skipDefaultBrowserCheck" +#define PREF_DEFAULTBROWSERCHECKCOUNT "browser.shell.defaultBrowserCheckCount" #define SHELLSERVICE_PROPERTIES "chrome://browser/locale/shellservice.properties" #define BRAND_PROPERTIES "chrome://branding/locale/brand.properties" diff --git a/application/palemoon/components/shell/nsWindowsShellService.cpp b/application/palemoon/components/shell/nsWindowsShellService.cpp index 813ec4fe1..c4039b95a 100644 --- a/application/palemoon/components/shell/nsWindowsShellService.cpp +++ b/application/palemoon/components/shell/nsWindowsShellService.cpp @@ -3,6 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsWindowsShellService.h" + #include "imgIContainer.h" #include "imgIRequest.h" #include "mozilla/gfx/2D.h" @@ -15,8 +17,8 @@ #include "nsIServiceManager.h" #include "nsIStringBundle.h" #include "nsNetUtil.h" +#include "nsServiceManagerUtils.h" #include "nsShellService.h" -#include "nsWindowsShellService.h" #include "nsIProcess.h" #include "nsICategoryManager.h" #include "nsBrowserCompsCID.h" @@ -27,6 +29,7 @@ #include "nsUnicharUtils.h" #include "nsIWinTaskbar.h" #include "nsISupportsPrimitives.h" +#include "nsIURLFormatter.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" #include "mozilla/WindowsVersion.h" @@ -47,6 +50,9 @@ #include <mbstring.h> #include <shlwapi.h> +#include <lm.h> +#undef ACCESS_READ + #ifndef MAX_BUF #define MAX_BUF 4096 #endif @@ -129,7 +135,7 @@ OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey) // The following keys are set to make PaleMoon appear in the Start Menu as the // browser: // -// HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\ +// HKCU\SOFTWARE\Clients\StartMenuInternet\PaleMoon.EXE\ // (default) REG_SZ <appname> // DefaultIcon (default) REG_SZ <apppath>,0 // InstallInfo HideIconsCommand REG_SZ <uninstpath> /HideShortcuts @@ -278,20 +284,15 @@ nsWindowsShellService::ShortcutMaintenance() return NS_ERROR_UNEXPECTED; NS_NAMED_LITERAL_CSTRING(prefName, "browser.taskbar.lastgroupid"); - nsCOMPtr<nsIPrefService> prefs = + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); if (!prefs) return NS_ERROR_UNEXPECTED; - nsCOMPtr<nsIPrefBranch> prefBranch; - prefs->GetBranch(nullptr, getter_AddRefs(prefBranch)); - if (!prefBranch) - return NS_ERROR_UNEXPECTED; - nsCOMPtr<nsISupportsString> prefString; - rv = prefBranch->GetComplexValue(prefName.get(), - NS_GET_IID(nsISupportsString), - getter_AddRefs(prefString)); + rv = prefs->GetComplexValue(prefName.get(), + NS_GET_IID(nsISupportsString), + getter_AddRefs(prefString)); if (NS_SUCCEEDED(rv)) { nsAutoString version; prefString->GetData(version); @@ -307,9 +308,9 @@ nsWindowsShellService::ShortcutMaintenance() return rv; prefString->SetData(appId); - rv = prefBranch->SetComplexValue(prefName.get(), - NS_GET_IID(nsISupportsString), - prefString); + rv = prefs->SetComplexValue(prefName.get(), + NS_GET_IID(nsISupportsString), + prefString); if (NS_FAILED(rv)) { NS_WARNING("Couldn't set last user model id!"); return NS_ERROR_UNEXPECTED; @@ -325,38 +326,47 @@ nsWindowsShellService::ShortcutMaintenance() } static bool -IsAARDefaultHTTP(IApplicationAssociationRegistration* pAAR, - bool* aIsDefaultBrowser) +IsAARDefault(const RefPtr<IApplicationAssociationRegistration>& pAAR, + LPCWSTR aClassName) { // Make sure the Prog ID matches what we have LPWSTR registeredApp; - HRESULT hr = pAAR->QueryCurrentDefault(L"http", AT_URLPROTOCOL, AL_EFFECTIVE, + bool isProtocol = *aClassName != L'.'; + ASSOCIATIONTYPE queryType = isProtocol ? AT_URLPROTOCOL : AT_FILEEXTENSION; + HRESULT hr = pAAR->QueryCurrentDefault(aClassName, queryType, AL_EFFECTIVE, ®isteredApp); - if (SUCCEEDED(hr)) { - LPCWSTR firefoxHTTPProgID = L"PaleMoonURL"; - *aIsDefaultBrowser = !wcsicmp(registeredApp, firefoxHTTPProgID); - CoTaskMemFree(registeredApp); - } else { - *aIsDefaultBrowser = false; + if (FAILED(hr)) { + return false; } - return SUCCEEDED(hr); + + LPCWSTR progID = isProtocol ? L"PaleMoonURL" : L"PaleMoonHTML"; + bool isDefault = !wcsicmp(registeredApp, progID); + CoTaskMemFree(registeredApp); + + return isDefault; } -static bool -IsAARDefaultHTML(IApplicationAssociationRegistration* pAAR, - bool* aIsDefaultBrowser) +static void +IsDefaultBrowserWin8(bool aCheckAllTypes, bool* aIsDefaultBrowser) { - LPWSTR registeredApp; - HRESULT hr = pAAR->QueryCurrentDefault(L".html", AT_FILEEXTENSION, AL_EFFECTIVE, - ®isteredApp); - if (SUCCEEDED(hr)) { - LPCWSTR firefoxHTMLProgID = L"PaleMoonHTML"; - *aIsDefaultBrowser = !wcsicmp(registeredApp, firefoxHTMLProgID); - CoTaskMemFree(registeredApp); - } else { - *aIsDefaultBrowser = false; + RefPtr<IApplicationAssociationRegistration> pAAR; + HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, + nullptr, + CLSCTX_INPROC, + IID_IApplicationAssociationRegistration, + getter_AddRefs(pAAR)); + if (FAILED(hr)) { + return; + } + + bool res = IsAARDefault(pAAR, L"http"); + if (*aIsDefaultBrowser) { + *aIsDefaultBrowser = res; + } + res = IsAARDefault(pAAR, L".html"); + if (*aIsDefaultBrowser && aCheckAllTypes) { + *aIsDefaultBrowser = res; } - return SUCCEEDED(hr); } /* @@ -369,37 +379,27 @@ bool nsWindowsShellService::IsDefaultBrowserVista(bool aCheckAllTypes, bool* aIsDefaultBrowser) { - IApplicationAssociationRegistration* pAAR; + RefPtr<IApplicationAssociationRegistration> pAAR; HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, nullptr, CLSCTX_INPROC, IID_IApplicationAssociationRegistration, - (void**)&pAAR); - - if (SUCCEEDED(hr)) { - if (aCheckAllTypes) { - BOOL res; - hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE, - APP_REG_NAME, - &res); - *aIsDefaultBrowser = res; - - // If we have all defaults, let's make sure that our ProgID - // is explicitly returned as well. Needed only for Windows 8. - if (*aIsDefaultBrowser && IsWin8OrLater()) { - IsAARDefaultHTTP(pAAR, aIsDefaultBrowser); - if (*aIsDefaultBrowser) { - IsAARDefaultHTML(pAAR, aIsDefaultBrowser); - } - } - } else { - IsAARDefaultHTTP(pAAR, aIsDefaultBrowser); - } + getter_AddRefs(pAAR)); + if (FAILED(hr)) { + return false; + } - pAAR->Release(); - return true; + if (aCheckAllTypes) { + BOOL res; + hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE, + APP_REG_NAME, + &res); + *aIsDefaultBrowser = res; + } else if (!IsWin8OrLater()) { + *aIsDefaultBrowser = IsAARDefault(pAAR, L"http"); } - return false; + + return true; } NS_IMETHODIMP @@ -407,12 +407,6 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck, bool aForAllTypes, bool* aIsDefaultBrowser) { - // If this is the first browser window, maintain internal state that we've - // checked this session (so that subsequent window opens don't show the - // default browser dialog). - if (aStartupCheck) - mCheckedThisSession = true; - // Assume we're the default unless one of the several checks below tell us // otherwise. *aIsDefaultBrowser = true; @@ -499,6 +493,9 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck, // previous checks show that PaleMoon is the default browser. if (*aIsDefaultBrowser) { IsDefaultBrowserVista(aForAllTypes, aIsDefaultBrowser); + if (IsWin8OrLater()) { + IsDefaultBrowserWin8(aForAllTypes, aIsDefaultBrowser); + } } // To handle the case where DDE isn't disabled due for a user because there @@ -603,13 +600,6 @@ nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck, return NS_OK; } -NS_IMETHODIMP -nsWindowsShellService::GetCanSetDesktopBackground(bool* aResult) -{ - *aResult = true; - return NS_OK; -} - static nsresult DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo) { @@ -628,14 +618,34 @@ DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo) return NS_ERROR_FAILURE; } - nsresult rv = - SUCCEEDED(SHOpenWithDialogFn(hwndParent, poainfo)) ? NS_OK : - NS_ERROR_FAILURE; + nsresult rv; + HRESULT hr = SHOpenWithDialogFn(hwndParent, poainfo); + if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))) { + rv = NS_OK; + } else { + rv = NS_ERROR_FAILURE; + } FreeLibrary(shellDLL); return rv; } nsresult +nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI() +{ + IApplicationAssociationRegistrationUI* pAARUI; + HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI, + NULL, + CLSCTX_INPROC, + IID_IApplicationAssociationRegistrationUI, + (void**)&pAARUI); + if (SUCCEEDED(hr)) { + hr = pAARUI->LaunchAdvancedAssociationUI(APP_REG_NAME); + pAARUI->Release(); + } + return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE; +} + +nsresult nsWindowsShellService::LaunchControlPanelDefaultPrograms() { // Build the path control.exe path safely @@ -651,7 +661,8 @@ nsWindowsShellService::LaunchControlPanelDefaultPrograms() return NS_ERROR_FAILURE; } - WCHAR params[] = L"control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram"; + WCHAR params[] = L"control.exe /name Microsoft.DefaultPrograms /page " + "pageDefaultProgram\\pageAdvancedSettings?pszAppName=" APP_REG_NAME; STARTUPINFOW si = {sizeof(si), 0}; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWDEFAULT; @@ -666,9 +677,62 @@ nsWindowsShellService::LaunchControlPanelDefaultPrograms() return NS_OK; } +static bool +IsWindowsLogonConnected() +{ + WCHAR userName[UNLEN + 1]; + DWORD size = ArrayLength(userName); + if (!GetUserNameW(userName, &size)) { + return false; + } + + LPUSER_INFO_24 info; + if (NetUserGetInfo(nullptr, userName, 24, (LPBYTE *)&info) + != NERR_Success) { + return false; + } + bool connected = info->usri24_internet_identity; + NetApiBufferFree(info); + + return connected; +} + +static bool +SettingsAppBelievesConnected() +{ + nsresult rv; + nsCOMPtr<nsIWindowsRegKey> regKey = + do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv); + if (NS_FAILED(rv)) { + return false; + } + + rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, + NS_LITERAL_STRING("SOFTWARE\\Microsoft\\Windows\\Shell\\Associations"), + nsIWindowsRegKey::ACCESS_READ); + if (NS_FAILED(rv)) { + return false; + } + + uint32_t value; + rv = regKey->ReadIntValue(NS_LITERAL_STRING("IsConnectedAtLogon"), &value); + if (NS_FAILED(rv)) { + return false; + } + + return !!value; +} + nsresult nsWindowsShellService::LaunchModernSettingsDialogDefaultApps() { + if (!IsWindowsBuildOrLater(14965) && + !IsWindowsLogonConnected() && SettingsAppBelievesConnected()) { + // Use the classic Control Panel to work around a bug of older + // builds of Windows 10. + return LaunchControlPanelDefaultPrograms(); + } + IApplicationActivationManager* pActivator; HRESULT hr = CoCreateInstance(CLSID_ApplicationActivationManager, nullptr, @@ -682,6 +746,15 @@ nsWindowsShellService::LaunchModernSettingsDialogDefaultApps() L"windows.immersivecontrolpanel_cw5n1h2txyewy" L"!microsoft.windows.immersivecontrolpanel", L"page=SettingsPageAppsDefaults", AO_NONE, &pid); + if (SUCCEEDED(hr)) { + // Do not check error because we could at least open + // the "Default apps" setting. + pActivator->ActivateApplication( + L"windows.immersivecontrolpanel_cw5n1h2txyewy" + L"!microsoft.windows.immersivecontrolpanel", + L"page=SettingsPageAppsDefaults" + L"&target=SystemSettings_DefaultApps_Browser", AO_NONE, &pid); + } pActivator->Release(); return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE; } @@ -689,6 +762,36 @@ nsWindowsShellService::LaunchModernSettingsDialogDefaultApps() } nsresult +nsWindowsShellService::InvokeHTTPOpenAsVerb() +{ + nsCOMPtr<nsIURLFormatter> formatter( + do_GetService("@mozilla.org/toolkit/URLFormatterService;1")); + if (!formatter) { + return NS_ERROR_UNEXPECTED; + } + + nsString urlStr; + nsresult rv = formatter->FormatURLPref( + NS_LITERAL_STRING("app.support.baseURL"), urlStr); + if (NS_FAILED(rv)) { + return rv; + } + if (!StringBeginsWith(urlStr, NS_LITERAL_STRING("https://"))) { + return NS_ERROR_FAILURE; + } + urlStr.AppendLiteral("win10-default-browser"); + + SHELLEXECUTEINFOW seinfo = { sizeof(SHELLEXECUTEINFOW) }; + seinfo.lpVerb = L"openas"; + seinfo.lpFile = urlStr.get(); + seinfo.nShow = SW_SHOWNORMAL; + if (!ShellExecuteExW(&seinfo)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult nsWindowsShellService::LaunchHTTPHandlerPane() { OPENASINFO info; @@ -716,16 +819,23 @@ nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers) nsresult rv = LaunchHelper(appHelperPath); if (NS_SUCCEEDED(rv) && IsWin8OrLater()) { if (aClaimAllTypes) { - rv = LaunchControlPanelDefaultPrograms(); + if (IsWin10OrLater()) { + rv = LaunchModernSettingsDialogDefaultApps(); + } else { + rv = LaunchControlPanelDefaultsSelectionUI(); + } // The above call should never really fail, but just in case // fall back to showing the HTTP association screen only. if (NS_FAILED(rv)) { - rv = LaunchHTTPHandlerPane(); + if (IsWin10OrLater()) { + rv = InvokeHTTPOpenAsVerb(); + } else { + rv = LaunchHTTPHandlerPane(); + } } } else { - // Windows 10 blocks attempts to load the HTTP Handler - // association dialog, so the modern Settings dialog - // is opened with the Default Apps view loaded. + // Windows 10 blocks attempts to load the + // HTTP Handler association dialog. if (IsWin10OrLater()) { rv = LaunchModernSettingsDialogDefaultApps(); } else { @@ -735,50 +845,20 @@ nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers) // The above call should never really fail, but just in case // fall back to showing control panel for all defaults if (NS_FAILED(rv)) { - rv = LaunchControlPanelDefaultPrograms(); + rv = LaunchControlPanelDefaultsSelectionUI(); } } } - return rv; -} - -NS_IMETHODIMP -nsWindowsShellService::GetShouldCheckDefaultBrowser(bool* aResult) -{ - NS_ENSURE_ARG_POINTER(aResult); - - // If we've already checked, the browser has been started and this is a - // new window open, and we don't want to check again. - if (mCheckedThisSession) { - *aResult = false; - return NS_OK; + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true); + // Reset the number of times the dialog should be shown + // before it is silenced. + (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0); } - nsCOMPtr<nsIPrefBranch> prefs; - nsresult rv; - nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = pserve->GetBranch("", getter_AddRefs(prefs)); - NS_ENSURE_SUCCESS(rv, rv); - - return prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult); -} - -NS_IMETHODIMP -nsWindowsShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck) -{ - nsCOMPtr<nsIPrefBranch> prefs; - nsresult rv; - - nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = pserve->GetBranch("", getter_AddRefs(prefs)); - NS_ENSURE_SUCCESS(rv, rv); - - return prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck); + return rv; } static nsresult @@ -912,7 +992,7 @@ nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement, // e.g. "Desktop Background.bmp" nsString fileLeafName; rv = shellBundle->GetStringFromName - (MOZ_UTF16("desktopBackgroundLeafNameWin"), + (u"desktopBackgroundLeafNameWin", getter_Copies(fileLeafName)); NS_ENSURE_SUCCESS(rv, rv); @@ -948,24 +1028,24 @@ nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement, nsAutoString style; switch (aPosition) { case BACKGROUND_TILE: - style.AssignLiteral("0"); - tile.AssignLiteral("1"); + style.Assign('0'); + tile.Assign('1'); break; case BACKGROUND_CENTER: - style.AssignLiteral("0"); - tile.AssignLiteral("0"); + style.Assign('0'); + tile.Assign('0'); break; case BACKGROUND_STRETCH: - style.AssignLiteral("2"); - tile.AssignLiteral("0"); + style.Assign('2'); + tile.Assign('0'); break; case BACKGROUND_FILL: style.AssignLiteral("10"); - tile.AssignLiteral("0"); + tile.Assign('0'); break; case BACKGROUND_FIT: - style.AssignLiteral("6"); - tile.AssignLiteral("0"); + style.Assign('6'); + tile.Assign('0'); break; } @@ -1023,7 +1103,7 @@ nsWindowsShellService::OpenApplication(int32_t aApplication) ::RegCloseKey(theKey); // Find the "open" command - application.AppendLiteral("\\"); + application.Append('\\'); application.Append(buf); application.AppendLiteral("\\shell\\open\\command"); @@ -1122,8 +1202,7 @@ nsWindowsShellService::SetDesktopBackgroundColor(uint32_t aColor) return regKey->Close(); } -nsWindowsShellService::nsWindowsShellService() : - mCheckedThisSession(false) +nsWindowsShellService::nsWindowsShellService() { } diff --git a/application/palemoon/components/shell/nsWindowsShellService.h b/application/palemoon/components/shell/nsWindowsShellService.h index f856ffd35..06c6c3c9b 100644 --- a/application/palemoon/components/shell/nsWindowsShellService.h +++ b/application/palemoon/components/shell/nsWindowsShellService.h @@ -16,9 +16,10 @@ class nsWindowsShellService : public nsIWindowsShellService { + virtual ~nsWindowsShellService(); + public: nsWindowsShellService(); - virtual ~nsWindowsShellService(); NS_DECL_ISUPPORTS NS_DECL_NSISHELLSERVICE @@ -26,12 +27,11 @@ public: protected: bool IsDefaultBrowserVista(bool aCheckAllTypes, bool* aIsDefaultBrowser); + nsresult LaunchControlPanelDefaultsSelectionUI(); nsresult LaunchControlPanelDefaultPrograms(); nsresult LaunchModernSettingsDialogDefaultApps(); + nsresult InvokeHTTPOpenAsVerb(); nsresult LaunchHTTPHandlerPane(); - -private: - bool mCheckedThisSession; }; #endif // nswindowsshellservice_h____ diff --git a/application/palemoon/config/version.txt b/application/palemoon/config/version.txt index 1d43844fa..b117d70fa 100644 --- a/application/palemoon/config/version.txt +++ b/application/palemoon/config/version.txt @@ -1 +1 @@ -27.9.0a1
\ No newline at end of file +28.0.0a1
\ No newline at end of file diff --git a/application/palemoon/configure.in b/application/palemoon/configure.in index 379c4e515..df5fb98a1 100644 --- a/application/palemoon/configure.in +++ b/application/palemoon/configure.in @@ -5,6 +5,11 @@ dnl License, v. 2.0. If a copy of the MPL was not distributed with this dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. dnl Things we need to carry from confvars.sh +AC_DEFINE(MOZ_PHOENIX) +AC_SUBST(MOZ_PHOENIX) + +AC_DEFINE(MC_PALEMOON) +AC_SUBST(MC_PALEMOON) dnl Optional parts of the build. diff --git a/application/palemoon/confvars.sh b/application/palemoon/confvars.sh index 7466d0c3c..705f992ee 100644 --- a/application/palemoon/confvars.sh +++ b/application/palemoon/confvars.sh @@ -3,58 +3,105 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -MOZ_APP_BASENAME=Palemoon +# Application Basename and Vendor +# MOZ_APP_BASENAME and MOZ_APP_VENDOR must not have spaces. +# These values where appropriate are hardcoded in application.ini +# to "Pale Moon" and "Moonchild Productions" respectively for +# Pale Moon +MOZ_APP_BASENAME=Palemoon MOZ_APP_VENDOR=Moonchild -MOZ_UPDATER=1 + +# Application Version +# MOZ_APP_VERSION is read from ./config/version.txt +# MOZ_APP_VERSION_DISPLAY is not used in Pale Moon so set it +# to MOZ_APP_VERSION +MOZ_APP_VERSION=`cat ${_topsrcdir}/$MOZ_BUILD_APP/config/version.txt` +MOZ_APP_VERSION_DISPLAY=$MOZ_APP_VERSION + +# Application ID +# This is a unique identifier used for the application +# Most frequently the AppID is used for targetApplication +# in extensions and for chrome manifests +MOZ_APP_ID={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4} + +# Use static Application INI File +MOZ_APP_STATIC_INI=1 + +# Application Branding +# The default is MOZ_BRANDING_DIRECTORY and should never point to +# official branding by default. +# Changing MOZ_*BRANDING_DIRECTORY requires a clobber because branding +# dependencies are broken. +# MOZ_APP_DISPLAYNAME will be set by [branding]/configure.sh +MOZ_BRANDING_DIRECTORY=$MOZ_BUILD_APP/branding/unofficial +MOZ_OFFICIAL_BRANDING_DIRECTORY=$MOZ_BUILD_APP/branding/official + +# Enables conditional code in the platform for Pale Moon only +MC_PALEMOON=1 + +# Enables conditional code in the platform for historically +# Firefox-like browsers MOZ_PHOENIX=1 -if test "$OS_TARGET" = "WINNT"; then - MOZ_BUNDLED_FONTS=1 -fi +# Browser Feature: Status bar Component +MOZ_BROWSER_STATUSBAR=1 -MOZ_CHROME_FILE_FORMAT=omni +# Browser Feature: Profile Migration Component +MOZ_PROFILE_MIGRATOR=1 + +# Platform Feature: Application Update Service +# MAR_CHANNEL_ID must not contained the follow 3 characters: ",\t" +# ACCEPTED_MAR_CHANNEL_IDS should usually be the same as MAR_CHANNEL_ID +# If more than one ID is needed, then you should use a comma seperated list. +MOZ_UPDATER=1 +MAR_CHANNEL_ID=palemoon-release +ACCEPTED_MAR_CHANNEL_IDS=palemoon-release + +# Platform Feature: Developer Tools +# XXX: Devtools are disabled until they can be made to work with Pale Moon +MOZ_DEVTOOLS= + +# Platform Feature: "Phoenix" Extensions Support aka Dual-guid system. +# Allows installation of Firefox GUID targeted extensions despite having +# a different Application ID +# On UXP this is a possible feature only for the Tycho Add-ons Manager +MOZ_PHOENIX_EXTENSIONS=1 + +# Platform Feature: Sync Service MOZ_SERVICES_COMMON=1 -MOZ_MEDIA_NAVIGATOR=1 -MOZ_SERVICES_CRYPTO=1 MOZ_SERVICES_SYNC=1 -MOZ_APP_VERSION=`cat ${_topsrcdir}/$MOZ_BUILD_APP/config/version.txt` -MOZ_EXTENSIONS_DEFAULT=" gio" - MOZ_SERVICES_FXACCOUNTS=1 -MOZ_DISABLE_EXPORT_JS=1 -MOZ_WEBGL_CONFORMANT=1 -MOZ_ACTIVITIES=1 +MOZ_SERVICES_CRYPTO=1 + +# Platform Feature: JS based Downloads Manager MOZ_JSDOWNLOADS=1 -MOZ_WEBM_ENCODER=1 -MOZ_PHOENIX_EXTENSIONS=1 -MOZ_BROWSER_STATUSBAR=1 +# Platform Feature: Conformant WebGL +# Exposes the "webgl" context name, which is reserved for +# conformant implementations. +MOZ_WEBGL_CONFORMANT=1 -#disabled by default on desktop. -MOZ_DEVTOOLS= +# Platform Feature: Windows Maintaince Service +# XXX: This is never used +if test "$OS_ARCH" = "WINNT"; then + MOZ_MAINTENANCE_SERVICE= +fi -# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh -# Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results, -# because branding dependencies are broken. -# MOZ_BRANDING_DIRECTORY is the default branding directory used when none is -# specified. It should never point to the "official" branding directory. -# For mozilla-beta, mozilla-release, or mozilla-central repositories, use -# "nightly" branding (until bug 659568 is fixed). -# For the mozilla-aurora repository, use "aurora". -MOZ_BRANDING_DIRECTORY=browser/branding/unofficial -MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official -# New Pale Moon App GUID -# Firefox MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} -MOZ_APP_ID={8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4} -# This should usually be the same as the value MAR_CHANNEL_ID. -# If more than one ID is needed, then you should use a comma separated list -# of values. -ACCEPTED_MAR_CHANNEL_IDS=palemoon-release -# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t " -MAR_CHANNEL_ID=palemoon-release -MOZ_PROFILE_MIGRATOR=1 -MOZ_EXTENSION_MANAGER=1 -MOZ_APP_STATIC_INI=1 +# Set the chrome packing format +# Possible values are omni, jar, and flat +# Currently, only omni and flat are supported +MOZ_CHROME_FILE_FORMAT=omni + +# Set the default top-level extensions +MOZ_EXTENSIONS_DEFAULT=" gio" + +# Fold Libs if test "$OS_TARGET" = "WINNT" -o "$OS_TARGET" = "Darwin"; then MOZ_FOLD_LIBS=1 fi + +# Include bundled fonts +if test "$OS_ARCH" = "WINNT" -o \ + "$OS_ARCH" = "Linux"; then + MOZ_BUNDLED_FONTS=1 +fi diff --git a/application/palemoon/fonts/EmojiOneMozilla.ttf b/application/palemoon/fonts/EmojiOneMozilla.ttf Binary files differdeleted file mode 100644 index 50356509d..000000000 --- a/application/palemoon/fonts/EmojiOneMozilla.ttf +++ /dev/null diff --git a/application/palemoon/fonts/README.txt b/application/palemoon/fonts/README.txt index 188ea3fff..bf5cb7e6e 100644 --- a/application/palemoon/fonts/README.txt +++ b/application/palemoon/fonts/README.txt @@ -1,9 +1,9 @@ -EmojiOne Mozilla +Twemoji Mozilla ================ -The upstream repository of EmojiOne Mozilla can be found at +The upstream repository of Twemoji Mozilla can be found at - https://github.com/mozilla/emojione-colr + https://github.com/mozilla/twemoji-colr Please refer commit history for the current version of the font. -This file purposely omit the version, so there is no need to update it here. +This file purposely omits the version, so there is no need to update it here. diff --git a/application/palemoon/fonts/TwemojiMozilla.ttf b/application/palemoon/fonts/TwemojiMozilla.ttf Binary files differnew file mode 100644 index 000000000..8139089f1 --- /dev/null +++ b/application/palemoon/fonts/TwemojiMozilla.ttf diff --git a/application/palemoon/fonts/moz.build b/application/palemoon/fonts/moz.build index 93d07120b..314d41bd0 100644 --- a/application/palemoon/fonts/moz.build +++ b/application/palemoon/fonts/moz.build @@ -7,5 +7,5 @@ if CONFIG['OS_ARCH'] in ('WINNT'): DIST_SUBDIR = '' FINAL_TARGET_FILES.fonts += [ - 'EmojiOneMozilla.ttf' + 'TwemojiMozilla.ttf' ] diff --git a/application/palemoon/installer/windows/Makefile.in b/application/palemoon/installer/windows/Makefile.in index 127456765..600bdfeb6 100644 --- a/application/palemoon/installer/windows/Makefile.in +++ b/application/palemoon/installer/windows/Makefile.in @@ -5,9 +5,7 @@ include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk CONFIG_DIR = instgen -SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/firefox/7zSD.sfx -APP_VERSION := $(shell cat $(srcdir)/../../config/version.txt) -DEFINES += -DAPP_VERSION=$(APP_VERSION) +SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/uxp/7zSD.sfx INSTALLER_FILES = \ app.tag \ @@ -16,6 +14,12 @@ INSTALLER_FILES = \ nsis/shared.nsh \ $(NULL) +ifdef MOZ_MAINTENANCE_SERVICE +INSTALLER_FILES += \ + nsis/maintenanceservice_installer.nsi \ + $(NULL) +endif + BRANDING_FILES = \ branding.nsi \ appname.bmp \ @@ -24,13 +28,6 @@ BRANDING_FILES = \ wizWatermark.bmp \ $(NULL) -DEFINES += \ - -DAB_CD=$(AB_CD) \ - -DMOZ_APP_NAME=$(MOZ_APP_NAME) \ - -DMOZ_APP_DISPLAYNAME="${MOZ_APP_DISPLAYNAME}" \ - -DMOZILLA_VERSION=${MOZILLA_VERSION} \ - $(NULL) - include $(topsrcdir)/config/config.mk ifdef LOCALE_MERGEDIR @@ -61,6 +58,17 @@ uninstaller:: --preprocess-locale $(topsrcdir) \ $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR) +# For building the maintenanceservice installer +ifdef MOZ_MAINTENANCE_SERVICE +maintenanceservice_installer:: + $(INSTALL) $(addprefix $(srcdir)/,$(INSTALLER_FILES)) $(CONFIG_DIR) + $(call py_action,preprocessor,-Fsubstitution $(DEFINES) $(ACDEFINES) \ + $(srcdir)/nsis/defines.nsi.in -o $(CONFIG_DIR)/defines.nsi) + $(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \ + --preprocess-locale $(topsrcdir) \ + $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR) +endif + $(CONFIG_DIR)/setup.exe:: $(RM) -r $(CONFIG_DIR) $(MKDIR) $(CONFIG_DIR) diff --git a/application/palemoon/installer/windows/moz.build b/application/palemoon/installer/windows/moz.build index 895d11993..12e7831ed 100644 --- a/application/palemoon/installer/windows/moz.build +++ b/application/palemoon/installer/windows/moz.build @@ -1,6 +1,11 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION'] + +DEFINES['MOZ_APP_NAME'] = CONFIG['MOZ_APP_NAME'] +DEFINES['MOZ_APP_DISPLAYNAME'] = CONFIG['MOZ_APP_DISPLAYNAME'] +DEFINES['MOZILLA_VERSION'] = CONFIG['MOZILLA_VERSION'] diff --git a/application/palemoon/installer/windows/nsis/defines.nsi.in b/application/palemoon/installer/windows/nsis/defines.nsi.in index ad171a5d6..97422c4f6 100644 --- a/application/palemoon/installer/windows/nsis/defines.nsi.in +++ b/application/palemoon/installer/windows/nsis/defines.nsi.in @@ -3,6 +3,23 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# Defining FunnelcakeVersion will append the value of StubURLVersionAppend to +# StubURLVersion, append the value of URLManualDownloadAppend to +# URLManualDownload, and append the value of URLStubDownloadAppend to +# URLStubDownload. The value of FunnelcakeVersion should not be defined when it +# is not used and when it is defined its value should never be empty. +# !define FunnelcakeVersion "999" + +!ifdef FunnelcakeVersion +!define URLManualDownloadAppend "&f=${FunnelcakeVersion}" +!define URLStubDownloadAppend "-f${FunnelcakeVersion}" +!define StubURLVersionAppend "-${FunnelcakeVersion}" +!else +!define URLManualDownloadAppend "" +!define URLStubDownloadAppend "" +!define StubURLVersionAppend "" +!endif + # These defines should match application.ini settings !define AppName "Pale Moon" !define AppVersion "@APP_VERSION@" @@ -14,13 +31,17 @@ !define DDEApplication "Pale Moon" !define AppRegName "Pale Moon" +!ifndef DEV_EDITION !define BrandShortName "@MOZ_APP_DISPLAYNAME@" +!endif !define BrandFullName "${BrandFullNameInternal}" -!define NO_UNINSTALL_SURVEY - -# !define CERTIFICATE_NAME "Mozilla Corporation" -# !define CERTIFICATE_ISSUER "Thawte Code Signing CA - G2" +!define CERTIFICATE_NAME "Mozilla Corporation" +!define CERTIFICATE_ISSUER "DigiCert SHA2 Assured ID Code Signing CA" +; Changing the name or issuer requires us to have both the old and the new +; in the registry at the same time, temporarily. +!define CERTIFICATE_NAME_PREVIOUS "Mozilla Corporation" +!define CERTIFICATE_ISSUER_PREVIOUS "DigiCert Assured ID Code Signing CA-1" # LSP_CATEGORIES is the permitted LSP categories for the application. Each LSP # category value is ANDed together to set multiple permitted categories. @@ -39,20 +60,26 @@ #ifdef HAVE_64BIT_BUILD !define HAVE_64BIT_BUILD !define ARCH "x64" -!define MinSupportedVer "Microsoft Windows Vista x64" +!define MinSupportedVer "Microsoft Windows 7 x64" #else !define ARCH "x86" -!define MinSupportedVer "Microsoft Windows Vista" +!define MinSupportedVer "Microsoft Windows 7" +#endif + +!define MinSupportedCPU "SSE2" + +#ifdef MOZ_MAINTENANCE_SERVICE +!define MOZ_MAINTENANCE_SERVICE #endif # File details shared by both the installer and uninstaller VIProductVersion "1.0.0.0" -VIAddVersionKey "ProductName" "Pale Moon" -VIAddVersionKey "CompanyName" "Moonchild Productions" +VIAddVersionKey "ProductName" "${BrandShortName}" +VIAddVersionKey "CompanyName" "${CompanyName}" #ifdef MOZ_OFFICIAL_BRANDING -VIAddVersionKey "LegalTrademarks" "Pale Moon is the intellectual property of Moonchild Productions." +VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of Moonchild Productions." #endif -VIAddVersionKey "LegalCopyright" "Moonchild Productions" +VIAddVersionKey "LegalCopyright" "${CompanyName}" VIAddVersionKey "FileVersion" "${AppVersion}" VIAddVersionKey "ProductVersion" "${AppVersion}" # Comments is not used but left below commented out for future reference diff --git a/application/palemoon/installer/windows/nsis/installer.nsi b/application/palemoon/installer/windows/nsis/installer.nsi index 147a56c9b..276b94f74 100644 --- a/application/palemoon/installer/windows/nsis/installer.nsi +++ b/application/palemoon/installer/windows/nsis/installer.nsi @@ -5,7 +5,7 @@ # Required Plugins: # AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in # ApplicationID http://nsis.sourceforge.net/ApplicationID_plug-in -# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash +# CityHash http://dxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash # ShellLink http://nsis.sourceforge.net/ShellLink_plug-in # UAC http://nsis.sourceforge.net/UAC_plug-in # ServicesHelper Mozilla specific plugin that is located in /other-licenses/nsis @@ -21,15 +21,25 @@ CRCCheck on RequestExecutionLevel user +; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can +; be removed after we require NSIS 3.0a2 or greater. +!ifdef NSIS_PACKEDVERSION + Unicode true + ManifestSupportedOS all + ManifestDPIAware true +!endif + !addplugindir ./ Var TmpVal Var InstallType Var AddStartMenuSC +Var AddTaskbarSC Var AddQuickLaunchSC Var AddDesktopSC Var InstallMaintenanceService Var PageName +Var PreventRebootRequired ; By defining NO_STARTMENU_DIR an installer that doesn't provide an option for ; an application's Start Menu PROGRAMS directory and doesn't define the @@ -82,6 +92,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe" !insertmacro InitHashAppModelId !insertmacro IsHandlerForInstallDir !insertmacro IsPinnedToTaskBar +!insertmacro IsUserAdmin !insertmacro LogDesktopShortcut !insertmacro LogQuickLaunchShortcut !insertmacro LogStartMenuShortcut @@ -90,6 +101,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe" !insertmacro RegCleanAppHandler !insertmacro RegCleanMain !insertmacro RegCleanUninstall +!insertmacro RemovePrecompleteEntries !insertmacro SetAppLSPCategories !insertmacro SetBrandNameVars !insertmacro UpdateShortcutAppModelIDs @@ -153,6 +165,11 @@ Page custom preOptions leaveOptions !define MUI_DIRECTORYPAGE_VERIFYONLEAVE !insertmacro MUI_PAGE_DIRECTORY +; Custom Components Page +!ifdef MOZ_MAINTENANCE_SERVICE +Page custom preComponents leaveComponents +!endif + ; Custom Shortcuts Page Page custom preShortcuts leaveShortcuts @@ -185,7 +202,42 @@ Section "-InstallStartCleanup" SetOutPath "$INSTDIR" ${StartInstallLog} "${BrandFullName}" "${AB_CD}" "${AppVersion}" "${GREVersion}" - ; Delete the app exe to prevent launching the app while we are installing. + StrCpy $R9 "true" + StrCpy $PreventRebootRequired "false" + ${GetParameters} $R8 + ${GetOptions} "$R8" "/INI=" $R7 + ${Unless} ${Errors} + ; The configuration file must also exist + ${If} ${FileExists} "$R7" + ReadINIStr $R9 $R7 "Install" "RemoveDistributionDir" + ReadINIStr $R8 $R7 "Install" "PreventRebootRequired" + ${If} $R8 == "true" + StrCpy $PreventRebootRequired "true" + ${EndIf} + ${EndIf} + ${EndUnless} + + ; Remove directories and files we always control before parsing the uninstall + ; log so empty directories can be removed. + ${If} ${FileExists} "$INSTDIR\updates" + RmDir /r "$INSTDIR\updates" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\updated" + RmDir /r "$INSTDIR\updated" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\defaults\shortcuts" + RmDir /r "$INSTDIR\defaults\shortcuts" + ${EndIf} + ; Only remove the distribution directory if it exists and if the installer + ; isn't launched with an ini file that has RemoveDistributionDir=false in the + ; install section. + ${If} ${FileExists} "$INSTDIR\distribution" + ${AndIf} $R9 != "false" + RmDir /r "$INSTDIR\distribution" + ${EndIf} + + ; Delete the app exe if present to prevent launching the app while we are + ; installing. ClearErrors ${DeleteFile} "$INSTDIR\${FileMainEXE}" ${If} ${Errors} @@ -201,9 +253,31 @@ Section "-InstallStartCleanup" ${InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" ; Remove the updates directory for Vista and above - ${CleanUpdateDirectories} "Mozilla\Firefox" "Mozilla\updates" + ${CleanUpdateDirectories} "Mozilla\Pale Moon" "Mozilla\updates" ${RemoveDeprecatedFiles} + ${RemovePrecompleteEntries} "false" + + ${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js" + Delete "$INSTDIR\defaults\pref\channel-prefs.js" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\defaults\pref" + RmDir "$INSTDIR\defaults\pref" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\defaults" + RmDir "$INSTDIR\defaults" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\uninstall" + ; Remove the uninstall directory that we control + RmDir /r "$INSTDIR\uninstall" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\update-settings.ini" + Delete "$INSTDIR\update-settings.ini" + ${EndIf} + + ; Explictly remove empty webapprt dir in case it exists (bug 757978). + RmDir "$INSTDIR\webapprt\components" + RmDir "$INSTDIR\webapprt" ${InstallStartCleanupCommon} SectionEnd @@ -215,8 +289,6 @@ Section "-Application" APP_IDX DetailPrint $(STATUS_INSTALL_APP) SetDetailsPrint none - RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}" - ${LogHeader} "Installing Main Files" ${CopyFilesFromDir} "$EXEDIR\core" "$INSTDIR" \ "$(ERROR_CREATE_DIRECTORY_PREFIX)" \ @@ -237,18 +309,6 @@ Section "-Application" APP_IDX ${LogMsg} "Registered: $INSTDIR\AccessibleMarshal.dll" ${EndIf} - ; Write extra files created by the application to the uninstall log so they - ; will be removed when the application is uninstalled. To remove an empty - ; directory write a bogus filename to the deepest directory and all empty - ; parent directories will be removed. - ${LogUninstall} "File: \components\compreg.dat" - ${LogUninstall} "File: \components\xpti.dat" - ${LogUninstall} "File: \active-update.xml" - ${LogUninstall} "File: \install.log" - ${LogUninstall} "File: \install_status.log" - ${LogUninstall} "File: \install_wizard.log" - ${LogUninstall} "File: \updates.xml" - ClearErrors ; Default for creating Start Menu shortcut @@ -336,10 +396,12 @@ Section "-Application" APP_IDX ; If we are writing to HKLM and create either the desktop or start menu ; shortcuts set IconsVisible to 1 otherwise to 0. + ; Taskbar shortcuts imply having a start menu shortcut. ${StrFilter} "${FileMainEXE}" "+" "" "" $R9 StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo" ${If} $AddDesktopSC == 1 ${OrIf} $AddStartMenuSC == 1 + ${OrIf} $AddTaskbarSC == 1 WriteRegDWORD HKLM "$0" "IconsVisible" 1 ${Else} WriteRegDWORD HKLM "$0" "IconsVisible" 0 @@ -353,16 +415,53 @@ Section "-Application" APP_IDX ; If we create either the desktop or start menu shortcuts, then ; set IconsVisible to 1 otherwise to 0. + ; Taskbar shortcuts imply having a start menu shortcut. ${StrFilter} "${FileMainEXE}" "+" "" "" $R9 StrCpy $0 "Software\Clients\StartMenuInternet\$R9\InstallInfo" ${If} $AddDesktopSC == 1 ${OrIf} $AddStartMenuSC == 1 + ${OrIf} $AddTaskbarSC == 1 WriteRegDWORD HKCU "$0" "IconsVisible" 1 ${Else} WriteRegDWORD HKCU "$0" "IconsVisible" 0 ${EndIf} ${EndIf} +!ifdef MOZ_MAINTENANCE_SERVICE + ; If the maintenance service page was displayed then a value was already + ; explicitly selected for installing the maintenance service and + ; and so InstallMaintenanceService will already be 0 or 1. + ; If the maintenance service page was not displayed then + ; InstallMaintenanceService will be equal to "". + ${If} $InstallMaintenanceService == "" + Call IsUserAdmin + Pop $R0 + ${If} $R0 == "true" + ; Only proceed if we have HKLM write access + ${AndIf} $TmpVal == "HKLM" + ; On Windows < XP SP3 we do not install the maintenance service. + ${If} ${IsWinXP} + ${AndIf} ${AtMostServicePack} 2 + StrCpy $InstallMaintenanceService "0" + ${Else} + ; The user is an admin, so we should default to installing the service. + StrCpy $InstallMaintenanceService "1" + ${EndIf} + ${Else} + ; The user is not admin, so we can't install the service. + StrCpy $InstallMaintenanceService "0" + ${EndIf} + ${EndIf} + + ${If} $InstallMaintenanceService == "1" + ; The user wants to install the maintenance service, so execute + ; the pre-packaged maintenance service installer. + ; This option can only be turned on if the user is an admin so there + ; is no need to use ExecShell w/ verb runas to enforce elevated. + nsExec::Exec "$\"$INSTDIR\maintenanceservice_installer.exe$\"" + ${EndIf} +!endif + ; These need special handling on uninstall since they may be overwritten by ; an install into a different location. StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\App Paths\${FileMainEXE}" @@ -437,6 +536,13 @@ Section "-Application" APP_IDX ${EndIf} ${EndIf} + ; Update lastwritetime of the Start Menu shortcut to clear the tile cache. + ${If} ${AtLeastWin8} + ${AndIf} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk" + FileOpen $0 "$SMPROGRAMS\${BrandFullName}.lnk" a + FileClose $0 + ${EndIf} + ${If} $AddDesktopSC == 1 CreateShortCut "$DESKTOP\${BrandFullName}.lnk" "$INSTDIR\${FileMainEXE}" ${If} ${FileExists} "$DESKTOP\${BrandFullName}.lnk" @@ -472,6 +578,13 @@ Section "-Application" APP_IDX ${EndIf} ${EndUnless} ${EndIf} + +!ifdef MOZ_MAINTENANCE_SERVICE + ${If} $TmpVal == "HKLM" + ; Add the registry keys for allowed certificates. + ${AddMaintCertKeys} + ${EndIf} +!endif SectionEnd ; Cleanup operations to perform at the end of the installation. @@ -481,8 +594,35 @@ Section "-InstallEndCleanup" SetDetailsPrint none ${Unless} ${Silent} + ClearErrors ${MUI_INSTALLOPTIONS_READ} $0 "summary.ini" "Field 4" "State" ${If} "$0" == "1" + ; NB: this code is duplicated in stub.nsi. Please keep in sync. + ; For data migration in the app, we want to know what the default browser + ; value was before we changed it. To do so, we read it here and store it + ; in our own registry key. + StrCpy $0 "" + ${If} ${AtLeastWinVista} + AppAssocReg::QueryCurrentDefault "http" "protocol" "effective" + Pop $1 + ; If the method hasn't failed, $1 will contain the progid. Check: + ${If} "$1" != "method failed" + ${AndIf} "$1" != "method not available" + ; Read the actual command from the progid + ReadRegStr $0 HKCR "$1\shell\open\command" "" + ${EndIf} + ${EndIf} + ; If using the App Association Registry didn't happen or failed, fall back + ; to the effective http default: + ${If} "$0" == "" + ReadRegStr $0 HKCR "http\shell\open\command" "" + ${EndIf} + ; If we have something other than empty string now, write the value. + ${If} "$0" != "" + ClearErrors + WriteRegStr HKCU "Software\Mozilla\Pale Moon" "OldDefaultBrowserCommand" "$0" + ${EndIf} + ${LogHeader} "Setting as the default browser" ClearErrors ${GetParameters} $0 @@ -493,46 +633,64 @@ Section "-InstallEndCleanup" GetFunctionAddress $0 SetAsDefaultAppUserHKCU UAC::ExecCodeSegment $0 ${EndIf} + ${ElseIfNot} ${Errors} + ${LogHeader} "Writing default-browser opt-out" + ClearErrors + WriteRegStr HKCU "Software\Mozilla\Pale Moon" "DefaultBrowserOptOut" "True" + ${If} ${Errors} + ${LogMsg} "Error writing default-browser opt-out" + ${EndIf} ${EndIf} - ; Adds a pinned Task Bar shortcut (see MigrateTaskBarShortcut for details). - ${MigrateTaskBarShortcut} ${EndUnless} - ${GetShortcutsLogPath} $0 - WriteIniStr "$0" "TASKBAR" "Migrated" "true" + ; Adds a pinned Task Bar shortcut (see MigrateTaskBarShortcut for details). + ${MigrateTaskBarShortcut} + + ; Add the Firewall entries during install + Call AddFirewallEntries ; Refresh desktop icons System::Call "shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_DWORDFLUSH}, i 0, i 0)" ${InstallEndCleanupCommon} + ${If} $PreventRebootRequired == "true" + SetRebootFlag false + ${EndIf} + ${If} ${RebootFlag} - ; When a reboot is required give SHChangeNotify time to finish the - ; refreshing the icons so the OS doesn't display the icons from helper.exe - Sleep 10000 - ${LogHeader} "Reboot Required To Finish Installation" - ; ${FileMainEXE}.moz-upgrade should never exist but just in case... - ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade" - Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-upgrade" - ${EndUnless} + ; Admin is required to delete files on reboot so only add the moz-delete if + ; the user is an admin. After calling UAC::IsAdmin $0 will equal 1 if the + ; user is an admin. + UAC::IsAdmin + ${If} "$0" == "1" + ; When a reboot is required give SHChangeNotify time to finish the + ; refreshing the icons so the OS doesn't display the icons from helper.exe + Sleep 10000 + ${LogHeader} "Reboot Required To Finish Installation" + ; ${FileMainEXE}.moz-upgrade should never exist but just in case... + ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-upgrade" + Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-upgrade" + ${EndUnless} - ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" - ClearErrors - Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-delete" - ${Unless} ${Errors} - Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete" + ${If} ${FileExists} "$INSTDIR\${FileMainEXE}" + ClearErrors + Rename "$INSTDIR\${FileMainEXE}" "$INSTDIR\${FileMainEXE}.moz-delete" + ${Unless} ${Errors} + Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete" + ${EndUnless} + ${EndIf} + + ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}" + CopyFiles /SILENT "$INSTDIR\uninstall\helper.exe" "$INSTDIR" + FileOpen $0 "$INSTDIR\${FileMainEXE}" w + FileWrite $0 "Will be deleted on restart" + Rename /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}" + FileClose $0 + Delete "$INSTDIR\${FileMainEXE}" + Rename "$INSTDIR\helper.exe" "$INSTDIR\${FileMainEXE}" ${EndUnless} ${EndIf} - - ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}" - CopyFiles /SILENT "$INSTDIR\uninstall\helper.exe" "$INSTDIR" - FileOpen $0 "$INSTDIR\${FileMainEXE}" w - FileWrite $0 "Will be deleted on restart" - Rename /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-upgrade" "$INSTDIR\${FileMainEXE}" - FileClose $0 - Delete "$INSTDIR\${FileMainEXE}" - Rename "$INSTDIR\helper.exe" "$INSTDIR\${FileMainEXE}" - ${EndUnless} ${EndIf} SectionEnd @@ -669,7 +827,9 @@ Function CheckExistingInstall FunctionEnd Function LaunchApp +!ifndef DEV_EDITION ${ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)" +!endif ClearErrors ${GetParameters} $0 @@ -776,9 +936,7 @@ Function leaveShortcuts Abort ${EndIf} ${MUI_INSTALLOPTIONS_READ} $AddDesktopSC "shortcuts.ini" "Field 2" "State" - - ; If we have a Metro browser and are Win8, then we don't have a Field 3 - ${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State" + ${MUI_INSTALLOPTIONS_READ} $AddStartMenuSC "shortcuts.ini" "Field 3" "State" ; Don't install the quick launch shortcut on Windows 7 ${Unless} ${AtLeastWin7} @@ -790,6 +948,59 @@ Function leaveShortcuts ${EndIf} FunctionEnd +!ifdef MOZ_MAINTENANCE_SERVICE +Function preComponents + ; If the service already exists, don't show this page + ServicesHelper::IsInstalled "MozillaMaintenance" + Pop $R9 + ${If} $R9 == 1 + ; The service already exists so don't show this page. + Abort + ${EndIf} + + ; On Windows < XP SP3 we do not install the maintenance service. + ${If} ${IsWinXP} + ${AndIf} ${AtMostServicePack} 2 + Abort + ${EndIf} + + ; Don't show the custom components page if the + ; user is not an admin + Call IsUserAdmin + Pop $R9 + ${If} $R9 != "true" + Abort + ${EndIf} + + ; Only show the maintenance service page if we have write access to HKLM + ClearErrors + WriteRegStr HKLM "Software\Mozilla" \ + "${BrandShortName}InstallerTest" "Write Test" + ${If} ${Errors} + ClearErrors + Abort + ${Else} + DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" + ${EndIf} + + StrCpy $PageName "Components" + ${CheckCustomCommon} + !insertmacro MUI_HEADER_TEXT "$(COMPONENTS_PAGE_TITLE)" "$(COMPONENTS_PAGE_SUBTITLE)" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "components.ini" +FunctionEnd + +Function leaveComponents + ${MUI_INSTALLOPTIONS_READ} $0 "components.ini" "Settings" "State" + ${If} $0 != 0 + Abort + ${EndIf} + ${MUI_INSTALLOPTIONS_READ} $InstallMaintenanceService "components.ini" "Field 2" "State" + ${If} $InstallType == ${INSTALLTYPE_CUSTOM} + Call CheckExistingInstall + ${EndIf} +FunctionEnd +!endif + Function preSummary StrCpy $PageName "Summary" ; Setup the summary.ini file for the Custom Summary Page @@ -838,14 +1049,14 @@ Function preSummary WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" "Write Test" ${Unless} ${Errors} DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" - ; Check if Firefox is the http handler for this user. + ; Check if Pale Moon is the http handler for this user. SetShellVarContext current ; Set SHCTX to the current user ${IsHandlerForInstallDir} "http" $R9 ${If} $TmpVal == "HKLM" SetShellVarContext all ; Set SHCTX to all users ${EndIf} - ; If Firefox isn't the http handler for this user show the option to set - ; Firefox as the default browser. + ; If Pale Moon isn't the http handler for this user show the option to set + ; Pale Moon as the default browser. ${If} "$R9" != "true" ${AndIf} ${AtMostWin2008R2} WriteINIStr "$PLUGINSDIR\summary.ini" "Settings" NumFields "4" @@ -926,7 +1137,46 @@ Function .onInit StrCpy $LANGUAGE 0 ${SetBrandNameVars} "$EXEDIR\core\distribution\setup.ini" - ${InstallOnInitCommon} "$(WARN_MIN_SUPPORTED_OS_MSG)" + ; Don't install on systems that don't support SSE2. The parameter value of + ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the + ; SSE2 instruction set is available. Result returned in $R7. + System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7" + + ; Windows NT 6.0 and lower are not supported on any architecture. + ${Unless} ${AtLeastWin7} + ${If} "$R7" == "0" + strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" + ${Else} + strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_MSG)" + ${EndIf} + MessageBox MB_OKCANCEL|MB_ICONSTOP "$R7" IDCANCEL +2 + ExecShell "open" "${URLSystemRequirements}" + Quit + ${EndUnless} + + ; SSE2 support + ${If} "$R7" == "0" + MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2 + ExecShell "open" "${URLSystemRequirements}" + Quit + ${EndIf} + +!ifdef HAVE_64BIT_BUILD + ${Unless} ${RunningX64} + MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_OSVER_MSG)" IDCANCEL +2 + ExecShell "open" "${URLSystemRequirements}" + Quit + ${EndUnless} + SetRegView 64 +!endif + + ${InstallOnInitCommon} "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)" + +; The commands inside this ifndef are needed prior to NSIS 3.0a2 and can be +; removed after we require NSIS 3.0a2 or greater. +!ifndef NSIS_PACKEDVERSION + System::Call 'user32::SetProcessDPIAware()' +!endif !insertmacro InitInstallOptionsFile "options.ini" !insertmacro InitInstallOptionsFile "shortcuts.ini" @@ -1016,6 +1266,25 @@ Function .onInit WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State "1" ${EndUnless} + ; Setup the components.ini file for the Components Page + WriteINIStr "$PLUGINSDIR\components.ini" "Settings" NumFields "2" + + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Type "label" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Text "$(OPTIONAL_COMPONENTS_DESC)" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Left "0" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Right "-1" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Top "5" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 1" Bottom "25" + + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Type "checkbox" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Text "$(MAINTENANCE_SERVICE_CHECKBOX_DESC)" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Left "0" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Right "-1" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Top "27" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Bottom "37" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" State "1" + WriteINIStr "$PLUGINSDIR\components.ini" "Field 2" Flags "GROUP" + ; There must always be a core directory. ${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8 SectionSetSize ${APP_IDX} $R5 diff --git a/application/palemoon/installer/windows/nsis/maintenanceservice_installer.nsi b/application/palemoon/installer/windows/nsis/maintenanceservice_installer.nsi new file mode 100644 index 000000000..1f73bac6a --- /dev/null +++ b/application/palemoon/installer/windows/nsis/maintenanceservice_installer.nsi @@ -0,0 +1,332 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs +!verbose 3 + +; 7-Zip provides better compression than the lzma from NSIS so we add the files +; uncompressed and use 7-Zip to create a SFX archive of it +SetDatablockOptimize on +SetCompress off +CRCCheck on + +RequestExecutionLevel admin + +; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can +; be removed after we require NSIS 3.0a2 or greater. +!ifdef NSIS_PACKEDVERSION + Unicode true + ManifestSupportedOS all + ManifestDPIAware true +!endif + +!addplugindir ./ + +; Variables +Var TempMaintServiceName +Var BrandFullNameDA +Var BrandFullName + +; Other included files may depend upon these includes! +; The following includes are provided by NSIS. +!include FileFunc.nsh +!include LogicLib.nsh +!include MUI.nsh +!include WinMessages.nsh +!include WinVer.nsh +!include WordFunc.nsh + +!insertmacro GetOptions +!insertmacro GetParameters +!insertmacro GetSize + +; The test slaves use this fallback key to run tests. +; And anyone that wants to run tests themselves should already have +; this installed. +!define FallbackKey \ + "SOFTWARE\Mozilla\MaintenanceService\3932ecacee736d366d6436db0f55bce4" + +!define CompanyName "Mozilla Corporation" +!define BrandFullNameInternal "" + +; The following includes are custom. +!include defines.nsi +; We keep defines.nsi defined so that we get other things like +; the version number, but we redefine BrandFullName +!define MaintFullName "Mozilla Maintenance Service" +!undef BrandFullName +!define BrandFullName "${MaintFullName}" + +!include common.nsh +!include locales.nsi + +VIAddVersionKey "FileDescription" "${MaintFullName} Installer" +VIAddVersionKey "OriginalFilename" "maintenanceservice_installer.exe" + +Name "${MaintFullName}" +OutFile "maintenanceservice_installer.exe" + +; Get installation folder from registry if available +InstallDirRegKey HKLM "Software\Mozilla\MaintenanceService" "" + +SetOverwrite on + +; serviceinstall.cpp also uses this key, in case the path is changed, update +; there too. +!define MaintUninstallKey \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService" + +; Always install into the 32-bit location even if we have a 64-bit build. +; This is because we use only 1 service for all Basilisk channels. +; Allow either x86 and x64 builds to exist at this location, depending on +; what is the latest build. +InstallDir "$PROGRAMFILES32\${MaintFullName}\" +ShowUnInstDetails nevershow + +################################################################################ +# Modern User Interface - MUI + +!define MUI_ICON setup.ico +!define MUI_UNICON setup.ico +!define MUI_WELCOMEPAGE_TITLE_3LINES +!define MUI_UNWELCOMEFINISHPAGE_BITMAP wizWatermark.bmp + +;Interface Settings +!define MUI_ABORTWARNING + +; Uninstaller Pages +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +################################################################################ +# Language + +!insertmacro MOZ_MUI_LANGUAGE 'baseLocale' +!verbose push +!verbose 3 +!include "overrideLocale.nsh" +!include "customLocale.nsh" +!verbose pop + +; Set this after the locale files to override it if it is in the locale +; using " " for BrandingText will hide the "Nullsoft Install System..." branding +BrandingText " " + +Function .onInit + ; Remove the current exe directory from the search order. + ; This only effects LoadLibrary calls and not implicitly loaded DLLs. + System::Call 'kernel32::SetDllDirectoryW(w "")' + + SetSilent silent + + ${Unless} ${AtLeastWin7} + Abort + ${EndUnless} +FunctionEnd + +Function un.onInit + ; Remove the current exe directory from the search order. + ; This only effects LoadLibrary calls and not implicitly loaded DLLs. + System::Call 'kernel32::SetDllDirectoryW(w "")' + +; The commands inside this ifndef are needed prior to NSIS 3.0a2 and can be +; removed after we require NSIS 3.0a2 or greater. +!ifndef NSIS_PACKEDVERSION + ${If} ${AtLeastWinVista} + System::Call 'user32::SetProcessDPIAware()' + ${EndIf} +!endif + + StrCpy $BrandFullNameDA "${MaintFullName}" + StrCpy $BrandFullName "${MaintFullName}" +FunctionEnd + +Section "MaintenanceService" + AllowSkipFiles off + + CreateDirectory $INSTDIR + SetOutPath $INSTDIR + + ; If the service already exists, then it will be stopped when upgrading it + ; via the maintenanceservice_tmp.exe command executed below. + ; The maintenanceservice_tmp.exe command will rename the file to + ; maintenanceservice.exe if maintenanceservice_tmp.exe is newer. + ; If the service does not exist yet, we install it and drop the file on + ; disk as maintenanceservice.exe directly. + StrCpy $TempMaintServiceName "maintenanceservice.exe" + IfFileExists "$INSTDIR\maintenanceservice.exe" 0 skipAlreadyExists + StrCpy $TempMaintServiceName "maintenanceservice_tmp.exe" + skipAlreadyExists: + + ; We always write out a copy and then decide whether to install it or + ; not via calling its 'install' cmdline which works by version comparison. + CopyFiles "$EXEDIR\maintenanceservice.exe" "$INSTDIR\$TempMaintServiceName" + + ; The updater.ini file is only used when performing an install or upgrade, + ; and only if that install or upgrade is successful. If an old updater.ini + ; happened to be copied into the maintenance service installation directory + ; but the service was not newer, the updater.ini file would be unused. + ; It is used to fill the description of the service on success. + CopyFiles "$EXEDIR\updater.ini" "$INSTDIR\updater.ini" + + ; Install the application maintenance service. + ; If a service already exists, the command line parameter will stop the + ; service and only install itself if it is newer than the already installed + ; service. If successful it will remove the old maintenanceservice.exe + ; and replace it with maintenanceservice_tmp.exe. + ClearErrors + ${GetParameters} $0 + ${GetOptions} "$0" "/Upgrade" $0 + ${If} ${Errors} + ExecWait '"$INSTDIR\$TempMaintServiceName" install' + ${Else} + ; The upgrade cmdline is the same as install except + ; It will fail if the service isn't already installed. + ExecWait '"$INSTDIR\$TempMaintServiceName" upgrade' + ${EndIf} + + WriteUninstaller "$INSTDIR\Uninstall.exe" + WriteRegStr HKLM "${MaintUninstallKey}" "DisplayName" "${MaintFullName}" + WriteRegStr HKLM "${MaintUninstallKey}" "UninstallString" \ + '"$INSTDIR\uninstall.exe"' + WriteRegStr HKLM "${MaintUninstallKey}" "DisplayIcon" \ + "$INSTDIR\Uninstall.exe,0" + WriteRegStr HKLM "${MaintUninstallKey}" "DisplayVersion" "${AppVersion}" + WriteRegStr HKLM "${MaintUninstallKey}" "Publisher" "Mozilla" + WriteRegStr HKLM "${MaintUninstallKey}" "Comments" "${BrandFullName}" + WriteRegDWORD HKLM "${MaintUninstallKey}" "NoModify" 1 + ${GetSize} "$INSTDIR" "/S=0K" $R2 $R3 $R4 + WriteRegDWORD HKLM "${MaintUninstallKey}" "EstimatedSize" $R2 + + ; Write out that a maintenance service was attempted. + ; We do this because on upgrades we will check this value and we only + ; want to install once on the first upgrade to maintenance service. + ; Also write out that we are currently installed, preferences will check + ; this value to determine if we should show the service update pref. + ; Since the Maintenance service can be installed either x86 or x64, + ; always use the 64-bit registry for checking if an attempt was made. + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1 + WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Installed" 1 + DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled" + + ; Included here for debug purposes only. + ; These keys are used to bypass the installation dir is a valid installation + ; check from the service so that tests can be run. + ; WriteRegStr HKLM "${FallbackKey}\0" "name" "Mozilla Corporation" + ; WriteRegStr HKLM "${FallbackKey}\0" "issuer" "DigiCert SHA2 Assured ID Code Signing CA" + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} +SectionEnd + +; By renaming before deleting we improve things slightly in case +; there is a file in use error. In this case a new install can happen. +Function un.RenameDelete + Pop $9 + ; If the .moz-delete file already exists previously, delete it + ; If it doesn't exist, the call is ignored. + ; We don't need to pass /REBOOTOK here since it was already marked that way + ; if it exists. + Delete "$9.moz-delete" + Rename "$9" "$9.moz-delete" + ${If} ${Errors} + Delete /REBOOTOK "$9" + ${Else} + Delete /REBOOTOK "$9.moz-delete" + ${EndIf} + ClearErrors +FunctionEnd + +Section "Uninstall" + ; Delete the service so that no updates will be attempted + ExecWait '"$INSTDIR\maintenanceservice.exe" uninstall' + + Push "$INSTDIR\updater.ini" + Call un.RenameDelete + Push "$INSTDIR\maintenanceservice.exe" + Call un.RenameDelete + Push "$INSTDIR\maintenanceservice_tmp.exe" + Call un.RenameDelete + Push "$INSTDIR\maintenanceservice.old" + Call un.RenameDelete + Push "$INSTDIR\Uninstall.exe" + Call un.RenameDelete + Push "$INSTDIR\update\updater.ini" + Call un.RenameDelete + Push "$INSTDIR\update\updater.exe" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-1.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-2.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-3.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-4.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-5.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-6.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-7.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-8.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-9.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-10.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-install.log" + Call un.RenameDelete + Push "$INSTDIR\logs\maintenanceservice-uninstall.log" + Call un.RenameDelete + SetShellVarContext all + Push "$APPDATA\Mozilla\logs\maintenanceservice.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-1.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-2.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-3.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-4.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-5.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-6.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-7.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-8.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-9.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-10.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-install.log" + Call un.RenameDelete + Push "$APPDATA\Mozilla\logs\maintenanceservice-uninstall.log" + Call un.RenameDelete + RMDir /REBOOTOK "$APPDATA\Mozilla\logs" + RMDir /REBOOTOK "$APPDATA\Mozilla" + RMDir /REBOOTOK "$INSTDIR\logs" + RMDir /REBOOTOK "$INSTDIR\update" + RMDir /REBOOTOK "$INSTDIR" + + DeleteRegKey HKLM "${MaintUninstallKey}" + + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "Installed" + DeleteRegValue HKLM "Software\Mozilla\MaintenanceService" "FFPrefetchDisabled" + DeleteRegKey HKLM "${FallbackKey}\" + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} +SectionEnd diff --git a/application/palemoon/installer/windows/nsis/shared.nsh b/application/palemoon/installer/windows/nsis/shared.nsh index 9770d4733..29136f47a 100644 --- a/application/palemoon/installer/windows/nsis/shared.nsh +++ b/application/palemoon/installer/windows/nsis/shared.nsh @@ -2,12 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -; The registration ID of the COM server which is used for choosing wether -; to launch the Win8 metro browser or desktop browser. -!define DELEGATE_EXECUTE_HANDLER_ID {5100FEC1-212B-4BF5-9BF8-3E650FD794A3} - !macro PostUpdate - ; PostUpdate is called from both session 0 and from the user session ; for service updates, make sure that we only register with the user session ; Otherwise ApplicationID::Set can fail intermittently with a file in use error. @@ -15,7 +10,7 @@ System::Call "kernel32::ProcessIdToSessionId(i $0, *i ${NSIS_MAX_STRLEN} r9)" ; Determine if we're the protected UserChoice default or not. If so fix the - ; start menu tile. In case there are 2 Pale Moon installations, we only do + ; start menu tile. In case there are 2 PaleMoon installations, we only do ; this if the application being updated is the default. ReadRegStr $0 HKCU "Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice" "ProgId" ${If} $0 == "PaleMoonURL" @@ -61,6 +56,9 @@ ; Win7 taskbar and start menu link maintenance Call FixShortcutAppModelIDs + ; Add the Firewall entries after an update + Call AddFirewallEntries + ; Only update the Clients\StartMenuInternet registry key values in HKLM if ; they don't exist or this installation is the same as the one set in those ; keys. @@ -100,6 +98,13 @@ ; root of the Start Menu Programs directory. ${MigrateStartMenuShortcut} + ; Update lastwritetime of the Start Menu shortcut to clear the tile cache. + ${If} ${AtLeastWin8} + ${AndIf} ${FileExists} "$SMPROGRAMS\${BrandFullName}.lnk" + FileOpen $0 "$SMPROGRAMS\${BrandFullName}.lnk" a + FileClose $0 + ${EndIf} + ; Adds a pinned Task Bar shortcut (see MigrateTaskBarShortcut for details). ${MigrateTaskBarShortcut} @@ -120,6 +125,50 @@ RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}" +!ifdef MOZ_MAINTENANCE_SERVICE + Call IsUserAdmin + Pop $R0 + ${If} $R0 == "true" + ; Only proceed if we have HKLM write access + ${AndIf} $TmpVal == "HKLM" + ; On Windows 2000 we do not install the maintenance service. + ${AndIf} ${AtLeastWinXP} + ; We check to see if the maintenance service install was already attempted. + ; Since the Maintenance service can be installed either x86 or x64, + ; always use the 64-bit registry for checking if an attempt was made. + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + ReadRegDWORD $5 HKLM "Software\Mozilla\MaintenanceService" "Attempted" + ClearErrors + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} + + ; Add the registry keys for allowed certificates. + ${AddMaintCertKeys} + + ; If the maintenance service is already installed, do nothing. + ; The maintenance service will launch: + ; maintenanceservice_installer.exe /Upgrade to upgrade the maintenance + ; service if necessary. If the update was done from updater.exe without + ; the service (i.e. service is failing), updater.exe will do the update of + ; the service. The reasons we do not do it here is because we don't want + ; to have to prompt for limited user accounts when the service isn't used + ; and we currently call the PostUpdate twice, once for the user and once + ; for the SYSTEM account. Also, this would stop the maintenance service + ; and we need a return result back to the service when run that way. + ${If} $5 == "" + ; An install of maintenance service was never attempted. + ; We know we are an Admin and that we have write access into HKLM + ; based on the above checks, so attempt to just run the EXE. + ; In the worst case, in case there is some edge case with the + ; IsAdmin check and the permissions check, the maintenance service + ; will just fail to be attempted to be installed. + nsExec::Exec "$\"$INSTDIR\maintenanceservice_installer.exe$\"" + ${EndIf} + ${EndIf} +!endif !macroend !define PostUpdate "!insertmacro PostUpdate" @@ -280,11 +329,11 @@ ${If} ${Errors} WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}" "" "PaleMoonHTML" ${EndIf} + WriteRegStr SHCTX "SOFTWARE\Classes\${FILE_TYPE}\OpenWithProgids" "PaleMoonHTML" "" !macroend !define AddAssociationIfNoneExist "!insertmacro AddAssociationIfNoneExist" - -; Adds the protocol and file handler registry entries for making Pale Moon the +; Adds the protocol and file handler registry entries for making PaleMoon the ; default handler (uses SHCTX). !macro SetHandlers ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8 @@ -318,10 +367,11 @@ WriteRegStr SHCTX "$0\.xhtml" "" "PaleMoonHTML" ${EndIf} - ;Register file associations, but only if they don't exist yet. + ${AddAssociationIfNoneExist} ".pdf" ${AddAssociationIfNoneExist} ".oga" ${AddAssociationIfNoneExist} ".ogg" ${AddAssociationIfNoneExist} ".ogv" + ${AddAssociationIfNoneExist} ".pdf" ${AddAssociationIfNoneExist} ".webm" ; An empty string is used for the 5th param because PaleMoonHTML is not a @@ -331,7 +381,6 @@ ${AddDisabledDDEHandlerValues} "PaleMoonURL" "$2" "$8,1" "${AppRegName} URL" \ "true" - ; An empty string is used for the 4th & 5th params because the following ; protocol handlers already have a display name and the additional keys ; required for a protocol handler. @@ -341,7 +390,7 @@ !macroend !define SetHandlers "!insertmacro SetHandlers" -; Adds the HKLM\Software\Clients\StartMenuInternet\{EXE} registry +; Adds the HKLM\Software\Clients\StartMenuInternet\FIREFOX.EXE registry ; entries (does not use SHCTX). ; ; The values for StartMenuInternet are only valid under HKLM and there can only @@ -420,7 +469,7 @@ ; The IconHandler reference for PaleMoonHTML can end up in an inconsistent state ; due to changes not being detected by the IconHandler for side by side ; installs (see bug 268512). The symptoms can be either an incorrect icon or no -; icon being displayed for files associated with Pale Moon (does not use SHCTX). +; icon being displayed for files associated with PaleMoon (does not use SHCTX). !macro FixShellIconHandler RegKey ClearErrors ReadRegStr $1 ${RegKey} "Software\Classes\PaleMoonHTML\ShellEx\IconHandler" "" @@ -436,37 +485,67 @@ ; Add Software\Mozilla\ registry entries (uses SHCTX). !macro SetAppKeys + ; Check if this is an ESR release and if so add registry values so it is + ; possible to determine that this is an ESR install (bug 726781). + ClearErrors + ${WordFind} "${UpdateChannel}" "esr" "E#" $3 + ${If} ${Errors} + StrCpy $3 "" + ${Else} + StrCpy $3 " ESR" + ${EndIf} + ${GetLongPath} "$INSTDIR" $8 - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Main" + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion}$3 (${ARCH} ${AB_CD})\Main" ${WriteRegStr2} $TmpVal "$0" "Install Directory" "$8" 0 ${WriteRegStr2} $TmpVal "$0" "PathToExe" "$8\${FileMainEXE}" 0 - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})\Uninstall" - ${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} (${ARCH} ${AB_CD})" 0 + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion}$3 (${ARCH} ${AB_CD})\Uninstall" + ${WriteRegStr2} $TmpVal "$0" "Description" "${BrandFullNameInternal} ${AppVersion}$3 (${ARCH} ${AB_CD})" 0 - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion} (${AB_CD})" - ${WriteRegStr2} $TmpVal "$0" "" "${AppVersion} (${AB_CD})" 0 + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}\${AppVersion}$3 (${ARCH} ${AB_CD})" + ${WriteRegStr2} $TmpVal "$0" "" "${AppVersion}$3 (${ARCH} ${AB_CD})" 0 + ${If} "$3" == "" + DeleteRegValue SHCTX "$0" "ESR" + ${Else} + ${WriteRegDWORD2} $TmpVal "$0" "ESR" 1 0 + ${EndIf} - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\bin" + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}$3\bin" ${WriteRegStr2} $TmpVal "$0" "PathToExe" "$8\${FileMainEXE}" 0 - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}\extensions" + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}$3\extensions" ${WriteRegStr2} $TmpVal "$0" "Components" "$8\components" 0 ${WriteRegStr2} $TmpVal "$0" "Plugins" "$8\plugins" 0 - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}" - ${WriteRegStr2} $TmpVal "$0" "GoannaVer" "${GREVersion}" 0 + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal} ${AppVersion}$3" + ${WriteRegStr2} $TmpVal "$0" "GeckoVer" "${GREVersion}" 0 + ${If} "$3" == "" + DeleteRegValue SHCTX "$0" "ESR" + ${Else} + ${WriteRegDWORD2} $TmpVal "$0" "ESR" 1 0 + ${EndIf} - StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}" + StrCpy $0 "Software\Mozilla\${BrandFullNameInternal}$3" ${WriteRegStr2} $TmpVal "$0" "" "${GREVersion}" 0 - ${WriteRegStr2} $TmpVal "$0" "CurrentVersion" "${AppVersion} (${AB_CD})" 0 + ${WriteRegStr2} $TmpVal "$0" "CurrentVersion" "${AppVersion}$3 (${ARCH} ${AB_CD})" 0 !macroend !define SetAppKeys "!insertmacro SetAppKeys" ; Add uninstall registry entries. This macro tests for write access to determine ; if the uninstall keys should be added to HKLM or HKCU. !macro SetUninstallKeys - StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} (${ARCH} ${AB_CD})" + ; Check if this is an ESR release and if so add registry values so it is + ; possible to determine that this is an ESR install (bug 726781). + ClearErrors + ${WordFind} "${UpdateChannel}" "esr" "E#" $3 + ${If} ${Errors} + StrCpy $3 "" + ${Else} + StrCpy $3 " ESR" + ${EndIf} + + StrCpy $0 "Software\Microsoft\Windows\CurrentVersion\Uninstall\${BrandFullNameInternal} ${AppVersion}$3 (${ARCH} ${AB_CD})" StrCpy $2 "" ClearErrors @@ -493,15 +572,24 @@ ${GetLongPath} "$INSTDIR" $8 ; Write the uninstall registry keys - ${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} (${ARCH} ${AB_CD})" 0 + ${WriteRegStr2} $1 "$0" "Comments" "${BrandFullNameInternal} ${AppVersion}$3 (${ARCH} ${AB_CD})" 0 ${WriteRegStr2} $1 "$0" "DisplayIcon" "$8\${FileMainEXE},0" 0 - ${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} (${ARCH} ${AB_CD})" 0 + ${WriteRegStr2} $1 "$0" "DisplayName" "${BrandFullNameInternal} ${AppVersion}$3 (${ARCH} ${AB_CD})" 0 ${WriteRegStr2} $1 "$0" "DisplayVersion" "${AppVersion}" 0 + ${WriteRegStr2} $1 "$0" "HelpLink" "${HelpLink}" 0 ${WriteRegStr2} $1 "$0" "InstallLocation" "$8" 0 ${WriteRegStr2} $1 "$0" "Publisher" "Moonchild Productions" 0 ${WriteRegStr2} $1 "$0" "UninstallString" "$\"$8\uninstall\helper.exe$\"" 0 - ${WriteRegStr2} $1 "$0" "URLInfoAbout" "${URLInfoAbout}" 0 + DeleteRegValue SHCTX "$0" "URLInfoAbout" +; Don't add URLUpdateInfo which is the release notes url except for the release +; and esr channels since nightly, aurora, and beta do not have release notes. +; Note: URLUpdateInfo is only defined in the official branding.nsi. +!ifdef URLUpdateInfo +!ifndef BETA_UPDATE_CHANNEL ${WriteRegStr2} $1 "$0" "URLUpdateInfo" "${URLUpdateInfo}" 0 +!endif +!endif + ${WriteRegStr2} $1 "$0" "URLInfoAbout" "${URLInfoAbout}" 0 ${WriteRegDWORD2} $1 "$0" "NoModify" 1 0 ${WriteRegDWORD2} $1 "$0" "NoRepair" 1 0 @@ -518,7 +606,7 @@ !define SetUninstallKeys "!insertmacro SetUninstallKeys" ; Due to a bug when associating some file handlers, only SHCTX was checked for -; some file types such as ".webm". SHCTX is set to HKCU or HKLM depending on +; some file types such as ".pdf". SHCTX is set to HKCU or HKLM depending on ; whether the installer has write access to HKLM. The bug would happen when ; HCKU was checked and didn't exist since programs aren't required to set the ; HKCU Software\Classes keys when associating handlers. The fix uses the merged @@ -534,7 +622,7 @@ ReadRegStr $2 HKCR "${FILE_TYPE}\PersistentHandler" "" ${If} "$2" != "" ; Since there is a persistent handler remove PaleMoonHTML as the default - ; value from both HKCU and HKLM if it is set to PaleMoonHTML. + ; value from both HKCU and HKLM if it set to PaleMoonHTML. ${If} "$0" == "PaleMoonHTML" DeleteRegValue HKCU "Software\Classes\${FILE_TYPE}" "" ${EndIf} @@ -542,7 +630,7 @@ DeleteRegValue HKLM "Software\Classes\${FILE_TYPE}" "" ${EndIf} ${ElseIf} "$0" == "PaleMoonHTML" - ; Since KHCU is set to PaleMoonHTML, remove it as the default value + ; Since KHCU is set to PaleMoonHTML remove PaleMoonHTML as the default value ; from HKCU if HKLM is set to a value other than an empty string. ${If} "$1" != "" DeleteRegValue HKCU "Software\Classes\${FILE_TYPE}" "" @@ -630,21 +718,68 @@ !macroend !define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers" +!ifdef MOZ_MAINTENANCE_SERVICE +; Adds maintenance service certificate keys for the install dir. +; For the cert to work, it must also be signed by a trusted cert for the user. +!macro AddMaintCertKeys + Push $R0 + ; Allow main Mozilla cert information for updates + ; This call will push the needed key on the stack + ServicesHelper::PathToUniqueRegistryPath "$INSTDIR" + Pop $R0 + ${If} $R0 != "" + ; More than one certificate can be specified in a different subfolder + ; for example: $R0\1, but each individual binary can be signed + ; with at most one certificate. A fallback certificate can only be used + ; if the binary is replaced with a different certificate. + ; We always use the 64bit registry for certs. + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + + ; PrefetchProcessName was originally used to experiment with deleting + ; Windows prefetch as a speed optimization. It is no longer used though. + DeleteRegValue HKLM "$R0" "prefetchProcessName" + + ; Setting the Attempted value will ensure that a new Maintenance Service + ; install will never be attempted again after this from updates. The value + ; is used only to see if updates should attempt new service installs. + WriteRegDWORD HKLM "Software\Mozilla\MaintenanceService" "Attempted" 1 + + ; These values associate the allowed certificates for the current + ; installation. + WriteRegStr HKLM "$R0\0" "name" "${CERTIFICATE_NAME}" + WriteRegStr HKLM "$R0\0" "issuer" "${CERTIFICATE_ISSUER}" + ; These values associate the allowed certificates for the previous + ; installation, so that we can update from it cleanly using the + ; old updater.exe (which will still have this signature). + WriteRegStr HKLM "$R0\1" "name" "${CERTIFICATE_NAME_PREVIOUS}" + WriteRegStr HKLM "$R0\1" "issuer" "${CERTIFICATE_ISSUER_PREVIOUS}" + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} + ClearErrors + ${EndIf} + ; Restore the previously used value back + Pop $R0 +!macroend +!define AddMaintCertKeys "!insertmacro AddMaintCertKeys" +!endif + ; Removes various registry entries for reasons noted below (does not use SHCTX). !macro RemoveDeprecatedKeys StrCpy $0 "SOFTWARE\Classes" ; Remove support for launching gopher urls from the shell during install or - ; update if the DefaultIcon is from palemoon.exe. + ; update if the DefaultIcon is from firefox.exe. ${RegCleanAppHandler} "gopher" ; Remove support for launching chrome urls from the shell during install or - ; update if the DefaultIcon is from palemoon.exe (Bug 301073). + ; update if the DefaultIcon is from firefox.exe (Bug 301073). ${RegCleanAppHandler} "chrome" - ; Remove the app compatibility registry key - StrCpy $0 "Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" - DeleteRegValue HKLM "$0" "$INSTDIR\${FileMainEXE}" - DeleteRegValue HKCU "$0" "$INSTDIR\${FileMainEXE}" + ; Remove protocol handler registry keys added by the MS shim + DeleteRegKey HKLM "Software\Classes\PaleMoon.URL" + DeleteRegKey HKCU "Software\Classes\PaleMoon.URL" ; Delete gopher from Capabilities\URLAssociations if it is present. ${StrFilter} "${FileMainEXE}" "+" "" "" $R9 @@ -671,147 +806,21 @@ RmDir /r /REBOOTOK "$INSTDIR\extensions\talkback@mozilla.org" ${EndIf} - ; Remove the Java Console extension (bug 597235) - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0012-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0012-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0013-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0013-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0014-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0014-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0015-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0015-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0016-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0016-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0017-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0017-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0018-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0018-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0019-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0019-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0020-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0020-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0021-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0021-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0022-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0015-0000-0022-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0001-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0001-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0002-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0002-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0003-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0003-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0004-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0004-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0005-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0005-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0006-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0006-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0007-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0007-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0010-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0010-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0011-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0011-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0012-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0012-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0013-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0013-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0014-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0014-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0015-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0015-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0016-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0016-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0017-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0017-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0018-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0018-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0019-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0019-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0020-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0020-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0021-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0021-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0022-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0022-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0023-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0023-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0024-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0024-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0025-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0025-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0026-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0026-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0027-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0027-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0028-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0028-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0029-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0029-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0030-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0030-ABCDEFFEDCBA}" - ${EndIf} + ; Remove the Java Console extension (bug 1165156) ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0031-ABCDEFFEDCBA}" RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0031-ABCDEFFEDCBA}" ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0032-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0032-ABCDEFFEDCBA}" + ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0034-ABCDEFFEDCBA}" + RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0034-ABCDEFFEDCBA}" ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0000-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0000-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0001-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0001-ABCDEFFEDCBA}" - ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0002-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0002-ABCDEFFEDCBA}" + ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0039-ABCDEFFEDCBA}" + RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0039-ABCDEFFEDCBA}" ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0003-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0003-ABCDEFFEDCBA}" + ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0045-ABCDEFFEDCBA}" + RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0045-ABCDEFFEDCBA}" ${EndIf} - ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0004-ABCDEFFEDCBA}" - RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0004-ABCDEFFEDCBA}" + ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0000-ABCDEFFEDCBA}" + RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0000-ABCDEFFEDCBA}" ${EndIf} !macroend !define RemoveDeprecatedFiles "!insertmacro RemoveDeprecatedFiles" @@ -876,15 +885,15 @@ ${If} $5 == "" ${Break} ${EndIf} - ${If} $5 == 233 ; ansi ?? + ${If} $5 == 233 ; ansi é StrCpy $0 "1" FileWriteByte $4 195 FileWriteByte $4 169 - ${ElseIf} $5 == 241 ; ansi ?? + ${ElseIf} $5 == 241 ; ansi ñ StrCpy $0 "1" FileWriteByte $4 195 FileWriteByte $4 177 - ${ElseIf} $5 == 252 ; ansi ?? + ${ElseIf} $5 == 252 ; ansi ü StrCpy $0 "1" FileWriteByte $4 195 FileWriteByte $4 188 @@ -926,17 +935,24 @@ ClearErrors WriteIniStr "$0" "TASKBAR" "Migrated" "true" ${If} ${AtLeastWin7} - ; No need to check the default on Win8 and later - ${If} ${AtMostWin2008R2} - ; Check if Pale Moon is the http handler for this user - SetShellVarContext current ; Set SHCTX to the current user - ${IsHandlerForInstallDir} "http" $R9 - ${If} $TmpVal == "HKLM" - SetShellVarContext all ; Set SHCTX to all users + ; If we didn't run the stub installer, AddTaskbarSC will be empty. + ; We determine whether to pin based on whether we're the default + ; browser, or if we're on win8 or later, we always pin. + ${If} $AddTaskbarSC == "" + ; No need to check the default on Win8 and later + ${If} ${AtMostWin2008R2} + ; Check if the PaleMoon is the http handler for this user + SetShellVarContext current ; Set SHCTX to the current user + ${IsHandlerForInstallDir} "http" $R9 + ${If} $TmpVal == "HKLM" + SetShellVarContext all ; Set SHCTX to all users + ${EndIf} ${EndIf} - ${EndIf} - ${If} "$R9" == "true" - ${OrIf} ${AtLeastWin8} + ${If} "$R9" == "true" + ${OrIf} ${AtLeastWin8} + ${PinToTaskBar} + ${EndIf} + ${ElseIf} $AddTaskbarSC == "1" ${PinToTaskBar} ${EndIf} ${EndIf} @@ -1152,17 +1168,86 @@ ; returns after the first check. Push "end" Push "AccessibleMarshal.dll" + Push "IA2Marshal.dll" Push "freebl3.dll" Push "nssckbi.dll" Push "nspr4.dll" Push "nssdbm3.dll" Push "mozsqlite3.dll" Push "xpcom.dll" + Push "crashreporter.exe" + Push "minidump-analyzer.exe" Push "updater.exe" Push "${FileMainEXE}" !macroend !define PushFilesToCheck "!insertmacro PushFilesToCheck" + +; Pushes the string "true" to the top of the stack if the Firewall service is +; running and pushes the string "false" to the top of the stack if it isn't. +!define SC_MANAGER_ALL_ACCESS 0x3F +!define SERVICE_QUERY_CONFIG 0x0001 +!define SERVICE_QUERY_STATUS 0x0004 +!define SERVICE_RUNNING 0x4 + +!macro IsFirewallSvcRunning + Push $R9 + Push $R8 + Push $R7 + Push $R6 + Push "false" + + System::Call 'advapi32::OpenSCManagerW(n, n, i ${SC_MANAGER_ALL_ACCESS}) i.R6' + ${If} $R6 != 0 + ; MpsSvc is the Firewall service on Windows Vista and above. + ; When opening the service with SERVICE_QUERY_CONFIG the return value will + ; be 0 if the service is not installed. + System::Call 'advapi32::OpenServiceW(i R6, t "MpsSvc", i ${SERVICE_QUERY_CONFIG}) i.R7' + ${If} $R7 != 0 + System::Call 'advapi32::CloseServiceHandle(i R7) n' + ; Open the service with SERVICE_QUERY_CONFIG so its status can be queried. + System::Call 'advapi32::OpenServiceW(i R6, t "MpsSvc", i ${SERVICE_QUERY_STATUS}) i.R7' + ${Else} + ; SharedAccess is the Firewall service on Windows XP. + ; When opening the service with SERVICE_QUERY_CONFIG the return value will + ; be 0 if the service is not installed. + System::Call 'advapi32::OpenServiceW(i R6, t "SharedAccess", i ${SERVICE_QUERY_CONFIG}) i.R7' + ${If} $R7 != 0 + System::Call 'advapi32::CloseServiceHandle(i R7) n' + ; Open the service with SERVICE_QUERY_CONFIG so its status can be + ; queried. + System::Call 'advapi32::OpenServiceW(i R6, t "SharedAccess", i ${SERVICE_QUERY_STATUS}) i.R7' + ${EndIf} + ${EndIf} + ; Did the calls to OpenServiceW succeed? + ${If} $R7 != 0 + System::Call '*(i,i,i,i,i,i,i) i.R9' + ; Query the current status of the service. + System::Call 'advapi32::QueryServiceStatus(i R7, i $R9) i' + System::Call '*$R9(i, i.R8)' + System::Free $R9 + System::Call 'advapi32::CloseServiceHandle(i R7) n' + IntFmt $R8 "0x%X" $R8 + ${If} $R8 == ${SERVICE_RUNNING} + Pop $R9 + Push "true" + ${EndIf} + ${EndIf} + System::Call 'advapi32::CloseServiceHandle(i R6) n' + ${EndIf} + + Exch 1 + Pop $R6 + Exch 1 + Pop $R7 + Exch 1 + Pop $R8 + Exch 1 + Pop $R9 +!macroend +!define IsFirewallSvcRunning "!insertmacro IsFirewallSvcRunning" +!define un.IsFirewallSvcRunning "!insertmacro IsFirewallSvcRunning" + ; Sets this installation as the default browser by setting the registry keys ; under HKEY_CURRENT_USER via registry calls and using the AppAssocReg NSIS ; plugin for Vista and above. This is a function instead of a macro so it is @@ -1214,7 +1299,7 @@ Function SetAsDefaultAppUserHKCU ${EndUnless} ${EndIf} ${RemoveDeprecatedKeys} - ${PinToTaskBar} + ${MigrateTaskBarShortcut} FunctionEnd ; Helper for updating the shortcut application model IDs. @@ -1225,6 +1310,15 @@ Function FixShortcutAppModelIDs ${EndIf} FunctionEnd +; Helper for adding Firewall exceptions during install and after app update. +Function AddFirewallEntries + ${IsFirewallSvcRunning} + Pop $0 + ${If} "$0" == "true" + liteFirewallW::AddRule "$INSTDIR\${FileMainEXE}" "${BrandShortName} ($INSTDIR)" + ${EndIf} +FunctionEnd + ; The !ifdef NO_LOG prevents warnings when compiling the installer.nsi due to ; this function only being used by the uninstaller.nsi. !ifdef NO_LOG @@ -1311,4 +1405,4 @@ Function SetAsDefaultAppUser FunctionEnd !define SetAsDefaultAppUser "Call SetAsDefaultAppUser" -!endif +!endif ; NO_LOG diff --git a/application/palemoon/installer/windows/nsis/uninstaller.nsi b/application/palemoon/installer/windows/nsis/uninstaller.nsi index 2ed5d9dfc..333fd33d6 100644 --- a/application/palemoon/installer/windows/nsis/uninstaller.nsi +++ b/application/palemoon/installer/windows/nsis/uninstaller.nsi @@ -4,7 +4,7 @@ # Required Plugins: # AppAssocReg http://nsis.sourceforge.net/Application_Association_Registration_plug-in -# CityHash http://mxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash +# CityHash http://dxr.mozilla.org/mozilla-central/source/other-licenses/nsis/Contrib/CityHash # ShellLink http://nsis.sourceforge.net/ShellLink_plug-in # UAC http://nsis.sourceforge.net/UAC_plug-in @@ -19,6 +19,14 @@ CRCCheck on RequestExecutionLevel user +; The commands inside this ifdef require NSIS 3.0a2 or greater so the ifdef can +; be removed after we require NSIS 3.0a2 or greater. +!ifdef NSIS_PACKEDVERSION + Unicode true + ManifestSupportedOS all + ManifestDPIAware true +!endif + !addplugindir ./ ; On Vista and above attempt to elevate Standard Users in addition to users that @@ -32,6 +40,7 @@ RequestExecutionLevel user "Software\Microsoft\Windows\CurrentVersion\Uninstall\MozillaMaintenanceService" Var TmpVal +Var MaintCertKey ; Other included files may depend upon these includes! ; The following includes are provided by NSIS. @@ -67,6 +76,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe" !insertmacro InitHashAppModelId !insertmacro IsHandlerForInstallDir !insertmacro IsPinnedToTaskBar +!insertmacro IsUserAdmin !insertmacro LogDesktopShortcut !insertmacro LogQuickLaunchShortcut !insertmacro LogStartMenuShortcut @@ -85,19 +95,18 @@ VIAddVersionKey "OriginalFilename" "helper.exe" !insertmacro un.CheckForFilesInUse !insertmacro un.CleanUpdateDirectories !insertmacro un.CleanVirtualStore -!insertmacro un.DeleteRelativeProfiles !insertmacro un.DeleteShortcuts !insertmacro un.GetLongPath !insertmacro un.GetSecondInstallPath !insertmacro un.InitHashAppModelId !insertmacro un.ManualCloseAppPrompt -!insertmacro un.ParseUninstallLog !insertmacro un.RegCleanAppHandler !insertmacro un.RegCleanFileHandler !insertmacro un.RegCleanMain !insertmacro un.RegCleanUninstall !insertmacro un.RegCleanProtocolHandler !insertmacro un.RemoveQuotesFromPath +!insertmacro un.RemovePrecompleteEntries !insertmacro un.SetAppLSPCategories !insertmacro un.SetBrandNameVars @@ -146,29 +155,69 @@ ShowUnInstDetails nevershow !insertmacro MUI_UNPAGE_WELCOME ; Custom Uninstall Confirm Page -UninstPage custom un.preConfirm un.leaveConfirm +UninstPage custom un.preConfirm ; Remove Files Page !insertmacro MUI_UNPAGE_INSTFILES ; Finish Page -; Don't setup the survey controls, functions, etc. when the application has -; defined NO_UNINSTALL_SURVEY -!ifndef NO_UNINSTALL_SURVEY -!define MUI_PAGE_CUSTOMFUNCTION_PRE un.preFinish -!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED -!define MUI_FINISHPAGE_SHOWREADME "" -!define MUI_FINISHPAGE_SHOWREADME_TEXT $(SURVEY_TEXT) -!define MUI_FINISHPAGE_SHOWREADME_FUNCTION un.Survey -!endif - !insertmacro MUI_UNPAGE_FINISH ; Use the default dialog for IDD_VERIFY for a simple Banner ChangeUI IDD_VERIFY "${NSISDIR}\Contrib\UIs\default.exe" ################################################################################ +# Helper Functions + +; This function is used to uninstall the maintenance service if the +; application currently being uninstalled is the last application to use the +; maintenance service. +Function un.UninstallServiceIfNotUsed + ; $0 will store if a subkey exists + ; $1 will store the first subkey if it exists or an empty string if it doesn't + ; Backup the old values + Push $0 + Push $1 + + ; The maintenance service always uses the 64-bit registry on x64 systems + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + + ; Figure out the number of subkeys + StrCpy $0 0 + ${Do} + EnumRegKey $1 HKLM "Software\Mozilla\MaintenanceService" $0 + ${If} "$1" == "" + ${ExitDo} + ${EndIf} + IntOp $0 $0 + 1 + ${Loop} + + ; Restore back the registry view + ${If} ${RunningX64} + SetRegView lastUsed + ${EndIf} + ${If} $0 == 0 + ; Get the path of the maintenance service uninstaller + ReadRegStr $1 HKLM ${MaintUninstallKey} "UninstallString" + + ; If the uninstall string does not exist, skip executing it + StrCmp $1 "" doneUninstall + + ; $1 is already a quoted string pointing to the install path + ; so we're already protected against paths with spaces + nsExec::Exec "$1 /S" +doneUninstall: + ${EndIf} + + ; Restore the old value of $1 and $0 + Pop $1 + Pop $0 +FunctionEnd + +################################################################################ # Install Sections ; Empty section required for the installer to compile as an uninstaller Section "" @@ -194,15 +243,6 @@ Section "Uninstall" ClearErrors ${EndIf} - ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State" - ${If} "$0" == "1" - ${un.DeleteRelativeProfiles} "Moonchild Productions\Pale Moon" - ${un.DeleteRelativeProfiles} "Moonchild Productions\MetroPM" - RmDir "$APPDATA\Mozilla\Extensions\{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}" - RmDir "$APPDATA\Mozilla\Extensions" - RmDir "$APPDATA\Mozilla" - ${EndIf} - ; setup the application model id registration value ${un.InitHashAppModelId} "$INSTDIR" "Software\Mozilla\${AppName}\TaskBarIDs" @@ -218,7 +258,7 @@ Section "Uninstall" ${EndIf} ; Remove the updates directory for Vista and above - ${un.CleanUpdateDirectories} "Moonchild Productions\Pale Moon" "Moonchild Productions\updates" + ${un.CleanUpdateDirectories} "Mozilla\PaleMoon" "Mozilla\updates" ; Remove any app model id's stored in the registry for this install path DeleteRegValue HKCU "Software\Mozilla\${AppName}\TaskBarIDs" "$INSTDIR" @@ -254,6 +294,10 @@ Section "Uninstall" ${un.RegCleanFileHandler} ".shtml" "PaleMoonHTML" ${un.RegCleanFileHandler} ".xht" "PaleMoonHTML" ${un.RegCleanFileHandler} ".xhtml" "PaleMoonHTML" + ${un.RegCleanFileHandler} ".oga" "PaleMoonHTML" + ${un.RegCleanFileHandler} ".ogg" "PaleMoonHTML" + ${un.RegCleanFileHandler} ".ogv" "PaleMoonHTML" + ${un.RegCleanFileHandler} ".pdf" "PaleMoonHTML" ${un.RegCleanFileHandler} ".webm" "PaleMoonHTML" ${EndIf} @@ -273,7 +317,7 @@ Section "Uninstall" ; The StartMenuInternet registry key is independent of the default browser ; settings. The XPInstall base un-installer always removes this key if it is ; uninstalling the default browser and it will always replace the keys when - ; installing even if there is another install of Firefox that is set as the + ; installing even if there is another install of PaleMoon that is set as the ; default browser. Now the key is always updated on install but it is only ; removed if it refers to this install location. ${If} "$INSTDIR" == "$R1" @@ -289,7 +333,7 @@ Section "Uninstall" ; The StartMenuInternet registry key is independent of the default browser ; settings. The XPInstall base un-installer always removes this key if it is ; uninstalling the default browser and it will always replace the keys when - ; installing even if there is another install of Firefox that is set as the + ; installing even if there is another install of PaleMoon that is set as the ; default browser. Now the key is always updated on install but it is only ; removed if it refers to this install location. ${If} "$INSTDIR" == "$R1" @@ -307,7 +351,7 @@ Section "Uninstall" StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe" DeleteRegKey HKLM "$0" DeleteRegKey HKCU "$0" - StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=firefox" + StrCpy $0 "Software\Classes\MIME\Database\Content Type\application/x-xpinstall;app=PaleMoon" DeleteRegKey HKLM "$0" DeleteRegKey HKCU "$0" ${Else} @@ -335,42 +379,63 @@ Section "Uninstall" ${If} ${FileExists} "$INSTDIR\distribution" RmDir /r /REBOOTOK "$INSTDIR\distribution" ${EndIf} - ${If} ${FileExists} "$INSTDIR\removed-files" - Delete /REBOOTOK "$INSTDIR\removed-files" - ${EndIf} ; Remove files that may be left behind by the application in the ; VirtualStore directory. ${un.CleanVirtualStore} - ; Parse the uninstall log to unregister dll's and remove all installed - ; files / directories this install is responsible for. - ${un.ParseUninstallLog} + ; Only unregister the dll if the registration points to this installation + ReadRegStr $R1 HKCR "CLSID\{0D68D6D0-D93D-4D08-A30D-F00DD1F45B24}\InProcServer32" "" + ${If} "$INSTDIR\AccessibleMarshal.dll" == "$R1" + ${UnregisterDLL} "$INSTDIR\AccessibleMarshal.dll" + ${EndIf} + + ${un.RemovePrecompleteEntries} "false" - ; Remove the uninstall directory that we control - RmDir /r /REBOOTOK "$INSTDIR\uninstall" + ${If} ${FileExists} "$INSTDIR\defaults\pref\channel-prefs.js" + Delete /REBOOTOK "$INSTDIR\defaults\pref\channel-prefs.js" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\defaults\pref" + RmDir /REBOOTOK "$INSTDIR\defaults\pref" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\defaults" + RmDir /REBOOTOK "$INSTDIR\defaults" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\uninstall" + ; Remove the uninstall directory that we control + RmDir /r /REBOOTOK "$INSTDIR\uninstall" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\install.log" + Delete /REBOOTOK "$INSTDIR\install.log" + ${EndIf} + ${If} ${FileExists} "$INSTDIR\update-settings.ini" + Delete /REBOOTOK "$INSTDIR\update-settings.ini" + ${EndIf} - ; Explictly remove empty webapprt dir in case it exists - ; See bug 757978 + ; Explicitly remove empty webapprt dir in case it exists (bug 757978). RmDir "$INSTDIR\webapprt\components" RmDir "$INSTDIR\webapprt" - RmDir /r /REBOOTOK "$INSTDIR\${TO_BE_DELETED}" - ; Remove the installation directory if it is empty - ${RemoveDir} "$INSTDIR" + RmDir "$INSTDIR" - ; If firefox.exe was successfully deleted yet we still need to restart to - ; remove other files create a dummy firefox.exe.moz-delete to prevent the + ; If PaleMoon.exe was successfully deleted yet we still need to restart to + ; remove other files create a dummy PaleMoon.exe.moz-delete to prevent the ; installer from allowing an install without restart when it is required ; to complete an uninstall. ${If} ${RebootFlag} - ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete" - FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w - FileWrite $0 "Will be deleted on restart" - Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete" - FileClose $0 - ${EndUnless} + ; Admin is required to delete files on reboot so only add the moz-delete if + ; the user is an admin. After calling UAC::IsAdmin $0 will equal 1 if the + ; user is an admin. + UAC::IsAdmin + ${If} "$0" == "1" + ${Unless} ${FileExists} "$INSTDIR\${FileMainEXE}.moz-delete" + FileOpen $0 "$INSTDIR\${FileMainEXE}.moz-delete" w + FileWrite $0 "Will be deleted on restart" + Delete /REBOOTOK "$INSTDIR\${FileMainEXE}.moz-delete" + FileClose $0 + ${EndUnless} + ${EndIf} ${EndIf} ; Refresh desktop icons otherwise the start menu internet item won't be @@ -378,19 +443,38 @@ Section "Uninstall" ; clients registry key by the OS under some conditions. System::Call "shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i 0, i 0, i 0)" -SectionEnd - -################################################################################ -# Helper Functions - -; Don't setup the survey controls, functions, etc. when the application has -; defined NO_UNINSTALL_SURVEY -!ifndef NO_UNINSTALL_SURVEY -Function un.Survey - Exec "$\"$TmpVal$\" $\"${SurveyURL}$\"" -FunctionEnd + ; Users who uninstall then reinstall expecting PaleMoon to use a clean profile + ; may be surprised during first-run. This key is checked during startup of PaleMoon and + ; subsequently deleted after checking. If the value is found during startup + ; the browser will offer to Reset PaleMoon. We use the UpdateChannel to match + ; uninstalls of PaleMoon-release with reinstalls of PaleMoon-release, for example. + WriteRegStr HKCU "Software\Mozilla\PaleMoon" "Uninstalled-${UpdateChannel}" "True" + +!ifdef MOZ_MAINTENANCE_SERVICE + ; Get the path the allowed cert is at and remove it + ; Keep this block of code last since it modfies the reg view + ServicesHelper::PathToUniqueRegistryPath "$INSTDIR" + Pop $MaintCertKey + ${If} $MaintCertKey != "" + ; Always use the 64bit registry for certs on 64bit systems. + ${If} ${RunningX64} + SetRegView 64 + ${EndIf} + DeleteRegKey HKLM "$MaintCertKey" + ${If} ${RunningX64} + SetRegView lastused + ${EndIf} + ${EndIf} + Call un.UninstallServiceIfNotUsed !endif + ${un.IsFirewallSvcRunning} + Pop $0 + ${If} "$0" == "true" + liteFirewallW::RemoveRule "$INSTDIR\${FileMainEXE}" "${BrandShortName} ($INSTDIR)" + ${EndIf} +SectionEnd + ################################################################################ # Language @@ -453,7 +537,7 @@ Function un.preConfirm ${EndIf} ; Setup the unconfirm.ini file for the Custom Uninstall Confirm Page - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "5" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "3" WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Type "label" WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 1" Text "$(UN_CONFIRM_UNINSTALLED_FROM)" @@ -473,44 +557,22 @@ Function un.preConfirm WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" Bottom "30" WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 2" flags "READONLY" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Type "checkbox" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Text "$(UN_REMOVE_PROFILES)" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Type "label" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Text "$(UN_CONFIRM_CLICK)" WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Left "0" WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Right "-1" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Top "40" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Bottom "50" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" State "0" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" flags "NOTIFY" - - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Type "text" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" State "$(UN_REMOVE_PROFILES_DESC)" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Left "0" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Right "-1" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Top "52" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Bottom "120" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" flags "MULTILINE|READONLY" - - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Type "label" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Text "$(UN_CONFIRM_CLICK)" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Left "0" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Right "-1" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Top "130" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 5" Bottom "150" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Top "130" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Bottom "150" ${If} "$TmpVal" == "true" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 6" Type "label" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 6" Text "$(SUMMARY_REBOOT_REQUIRED_UNINSTALL)" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 6" Left "0" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 6" Right "-1" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 6" Top "35" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 6" Bottom "45" - - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "6" - - ; To insert this control reset Top / Bottom for controls below this one - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Top "55" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 3" Bottom "65" - WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Top "67" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Type "label" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Text "$(SUMMARY_REBOOT_REQUIRED_UNINSTALL)" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Left "0" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Right "-1" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Top "35" + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Field 4" Bottom "45" + + WriteINIStr "$PLUGINSDIR\unconfirm.ini" "Settings" NumFields "4" ${EndIf} !insertmacro MUI_HEADER_TEXT "$(UN_CONFIRM_PAGE_TITLE)" "$(UN_CONFIRM_PAGE_SUBTITLE)" @@ -518,72 +580,12 @@ Function un.preConfirm ; focus. This sets the focus to the Install button instead. !insertmacro MUI_INSTALLOPTIONS_INITDIALOG "unconfirm.ini" GetDlgItem $0 $HWNDPARENT 1 - ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 4" "HWND" - SetCtlColors $1 0x000000 0xFFFFEE - ShowWindow $1 ${SW_HIDE} System::Call "user32::SetFocus(i r0, i 0x0007, i,i)i" ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 2" "HWND" SendMessage $1 ${WM_SETTEXT} 0 "STR:$INSTDIR" !insertmacro MUI_INSTALLOPTIONS_SHOW FunctionEnd -Function un.leaveConfirm - ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Settings" "State" - StrCmp $0 "3" +1 continue - ${MUI_INSTALLOPTIONS_READ} $0 "unconfirm.ini" "Field 3" "State" - ${MUI_INSTALLOPTIONS_READ} $1 "unconfirm.ini" "Field 4" "HWND" - StrCmp $0 1 +1 +3 - ShowWindow $1 ${SW_SHOW} - Abort - - ShowWindow $1 ${SW_HIDE} - Abort - - continue: - - ; Try to delete the app executable and if we can't delete it try to find the - ; app's message window and prompt the user to close the app. This allows - ; running an instance that is located in another directory. If for whatever - ; reason there is no message window we will just rename the app's files and - ; then remove them on restart if they are in use. - ClearErrors - ${DeleteFile} "$INSTDIR\${FileMainEXE}" - ${If} ${Errors} - ${un.ManualCloseAppPrompt} "${WindowClass}" "$(WARN_MANUALLY_CLOSE_APP_UNINSTALL)" - ${EndIf} -FunctionEnd - -!ifndef NO_UNINSTALL_SURVEY -Function un.preFinish - ; Do not modify the finish page if there is a reboot pending - ${Unless} ${RebootFlag} - ; Setup the survey controls, functions, etc. - StrCpy $TmpVal "SOFTWARE\Microsoft\IE Setup\Setup" - ClearErrors - ReadRegStr $0 HKLM $TmpVal "Path" - ${If} ${Errors} - !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3" - ${Else} - ExpandEnvStrings $0 "$0" ; this value will usually contain %programfiles% - ${If} $0 != "\" - StrCpy $0 "$0\" - ${EndIf} - StrCpy $0 "$0\iexplore.exe" - ClearErrors - GetFullPathName $TmpVal $0 - ${If} ${Errors} - !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "NumFields" "3" - ${Else} - ; When we add an optional action to the finish page the cancel button - ; is enabled. This disables it and leaves the finish button as the - ; only choice. - !insertmacro MUI_INSTALLOPTIONS_WRITE "ioSpecial.ini" "settings" "cancelenabled" "0" - ${EndIf} - ${EndIf} - ${EndUnless} -FunctionEnd -!endif - ################################################################################ # Initialization Functions @@ -605,6 +607,14 @@ Function un.onInit ${un.UninstallUnOnInitCommon} +; The commands inside this ifndef are needed prior to NSIS 3.0a2 and can be +; removed after we require NSIS 3.0a2 or greater. +!ifndef NSIS_PACKEDVERSION + ${If} ${AtLeastWinVista} + System::Call 'user32::SetProcessDPIAware()' + ${EndIf} +!endif + !insertmacro InitInstallOptionsFile "unconfirm.ini" FunctionEnd diff --git a/application/palemoon/installer/windows/stub.tag b/application/palemoon/installer/windows/stub.tag deleted file mode 100644 index 4eae031d6..000000000 --- a/application/palemoon/installer/windows/stub.tag +++ /dev/null @@ -1,4 +0,0 @@ -;!@Install@!UTF-8! -Title="Pale Moon" -RunProgram="setup-stub.exe" -;!@InstallEnd@!
\ No newline at end of file diff --git a/application/palemoon/locales/Makefile.in b/application/palemoon/locales/Makefile.in index f00d7a040..5720a76df 100644 --- a/application/palemoon/locales/Makefile.in +++ b/application/palemoon/locales/Makefile.in @@ -96,11 +96,7 @@ NO_JA_JP_MAC_AB_CD := $(if $(filter ja-JP-mac, $(AB_CD)),ja,$(AB_CD)) %/defaults/profile/bookmarks.html: bookmarks.inc generic/profile/bookmarks.html.in $(SYSINSTALL) -D $(dir $@) - $(call py_action,preprocessor, \ - -I $< \ - -DAB_CD=$(NO_JA_JP_MAC_AB_CD) \ - $(srcdir)/generic/profile/bookmarks.html.in \ - -o $@) + $(call py_action,preprocessor,$< -DAB_CD=$(NO_JA_JP_MAC_AB_CD) $(srcdir)/generic/profile/bookmarks.html.in -o $@) libs:: $(FINAL_TARGET)/defaults/profile/bookmarks.html ; @@ -124,10 +120,10 @@ searchplugins: $(addprefix $(FINAL_TARGET)/searchplugins/,$(SEARCHPLUGINS)) libs-%: $(NSINSTALL) -D $(DIST)/install - @$(MAKE) -C ../../toolkit/locales libs-$* - @$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* - @$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* - @$(MAKE) -C ../../intl/locales AB_CD=$* XPI_NAME=locale-$* + @$(MAKE) -C ../../../toolkit/locales libs-$* + @$(MAKE) -C ../../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* + @$(MAKE) -C ../../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* + @$(MAKE) -C ../../../intl/locales AB_CD=$* XPI_NAME=locale-$* @$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR) @$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$* diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.dtd b/application/palemoon/locales/en-US/chrome/browser/browser.dtd index fe5f64854..0225f422b 100644 --- a/application/palemoon/locales/en-US/chrome/browser/browser.dtd +++ b/application/palemoon/locales/en-US/chrome/browser/browser.dtd @@ -337,7 +337,6 @@ These should match what Safari and other Apple applications use on OS X Lion. -- <!ENTITY appMenuSafeMode.label "Restart in Safe Mode…"> <!ENTITY openCmd.commandkey "l"> -<!ENTITY urlbar.placeholder2 "Search or enter address"> <!ENTITY urlbar.accesskey "d"> <!ENTITY urlbar.switchToTab.label "Switch to tab:"> diff --git a/application/palemoon/locales/en-US/chrome/browser/browser.properties b/application/palemoon/locales/en-US/chrome/browser/browser.properties index 5f75502ed..8b3fea4d5 100644 --- a/application/palemoon/locales/en-US/chrome/browser/browser.properties +++ b/application/palemoon/locales/en-US/chrome/browser/browser.properties @@ -220,6 +220,8 @@ tabHistory.goBack=Go back to this page tabHistory.goForward=Go forward to this page # URL Bar +urlbar.placeholder=Search or enter address +urlbar.placeholderURLOnly=Enter address pasteAndGo.label=Paste & Go # Block autorefresh diff --git a/application/palemoon/moz.configure b/application/palemoon/moz.configure new file mode 100644 index 000000000..631980d15 --- /dev/null +++ b/application/palemoon/moz.configure @@ -0,0 +1,12 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +imply_option('MOZ_PLACES', True) +imply_option('MOZ_SERVICES_HEALTHREPORT', True) +imply_option('MOZ_SERVICES_SYNC', True) +imply_option('MOZ_SERVICES_CLOUDSYNC', True) + +include('../../toolkit/moz.configure') diff --git a/browser/fonts/EmojiOneMozilla.ttf b/browser/fonts/EmojiOneMozilla.ttf Binary files differdeleted file mode 100644 index 50356509d..000000000 --- a/browser/fonts/EmojiOneMozilla.ttf +++ /dev/null diff --git a/browser/fonts/README.txt b/browser/fonts/README.txt index 188ea3fff..ac1f6d9de 100644 --- a/browser/fonts/README.txt +++ b/browser/fonts/README.txt @@ -1,9 +1,9 @@ -EmojiOne Mozilla +Twemoji Mozilla ================ -The upstream repository of EmojiOne Mozilla can be found at +The upstream repository of Twemoji Mozilla can be found at - https://github.com/mozilla/emojione-colr + https://github.com/mozilla/twemoji-colr Please refer commit history for the current version of the font. This file purposely omit the version, so there is no need to update it here. diff --git a/browser/fonts/TwemojiMozilla.ttf b/browser/fonts/TwemojiMozilla.ttf Binary files differnew file mode 100644 index 000000000..1933891d9 --- /dev/null +++ b/browser/fonts/TwemojiMozilla.ttf diff --git a/browser/fonts/moz.build b/browser/fonts/moz.build index b1a43e528..5cb98333b 100644 --- a/browser/fonts/moz.build +++ b/browser/fonts/moz.build @@ -7,5 +7,5 @@ if CONFIG['OS_ARCH'] in ('WINNT', 'Linux'): DIST_SUBDIR = '' FINAL_TARGET_FILES.fonts += [ - 'EmojiOneMozilla.ttf' + 'TwemojiMozilla.ttf' ] diff --git a/db/sqlite3/src/sqlite3.c b/db/sqlite3/src/sqlite3.c index 9c8fd6204..320d6355e 100644 --- a/db/sqlite3/src/sqlite3.c +++ b/db/sqlite3/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.19.3. By combining all the individual C code files into this +** version 3.21.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -22,6 +22,761 @@ #ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static #endif +/************** Begin file ctime.c *******************************************/ +/* +** 2010 February 23 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file implements routines used to report what compile-time options +** SQLite was built with. +*/ + +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) +#include "config.h" +#define SQLITECONFIG_H 1 +#endif + +/* These macros are provided to "stringify" the value of the define +** for those options in which the value is meaningful. */ +#define CTIMEOPT_VAL_(opt) #opt +#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) + +/* +** An array of names of all compile-time options. This array should +** be sorted A-Z. +** +** This array looks large, but in a typical installation actually uses +** only a handful of compile-time options, so most times this array is usually +** rather short and uses little memory space. +*/ +static const char * const sqlite3azCompileOpt[] = { + +/* +** BEGIN CODE GENERATED BY tool/mkctime.tcl +*/ +#if SQLITE_32BIT_ROWID + "32BIT_ROWID", +#endif +#if SQLITE_4_BYTE_ALIGNED_MALLOC + "4_BYTE_ALIGNED_MALLOC", +#endif +#if SQLITE_64BIT_STATS + "64BIT_STATS", +#endif +#if SQLITE_ALLOW_COVERING_INDEX_SCAN + "ALLOW_COVERING_INDEX_SCAN", +#endif +#if SQLITE_ALLOW_URI_AUTHORITY + "ALLOW_URI_AUTHORITY", +#endif +#ifdef SQLITE_BITMASK_TYPE + "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE), +#endif +#if SQLITE_BUG_COMPATIBLE_20160819 + "BUG_COMPATIBLE_20160819", +#endif +#if SQLITE_CASE_SENSITIVE_LIKE + "CASE_SENSITIVE_LIKE", +#endif +#if SQLITE_CHECK_PAGES + "CHECK_PAGES", +#endif +#if defined(__clang__) && defined(__clang_major__) + "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "." + CTIMEOPT_VAL(__clang_minor__) "." + CTIMEOPT_VAL(__clang_patchlevel__), +#elif defined(_MSC_VER) + "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER), +#elif defined(__GNUC__) && defined(__VERSION__) + "COMPILER=gcc-" __VERSION__, +#endif +#if SQLITE_COVERAGE_TEST + "COVERAGE_TEST", +#endif +#if SQLITE_DEBUG + "DEBUG", +#endif +#if SQLITE_DEFAULT_AUTOMATIC_INDEX + "DEFAULT_AUTOMATIC_INDEX", +#endif +#if SQLITE_DEFAULT_AUTOVACUUM + "DEFAULT_AUTOVACUUM", +#endif +#ifdef SQLITE_DEFAULT_CACHE_SIZE + "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE), +#endif +#if SQLITE_DEFAULT_CKPTFULLFSYNC + "DEFAULT_CKPTFULLFSYNC", +#endif +#ifdef SQLITE_DEFAULT_FILE_FORMAT + "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT), +#endif +#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS + "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS), +#endif +#if SQLITE_DEFAULT_FOREIGN_KEYS + "DEFAULT_FOREIGN_KEYS", +#endif +#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT), +#endif +#ifdef SQLITE_DEFAULT_LOCKING_MODE + "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), +#endif +#ifdef SQLITE_DEFAULT_LOOKASIDE + "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE), +#endif +#if SQLITE_DEFAULT_MEMSTATUS + "DEFAULT_MEMSTATUS", +#endif +#ifdef SQLITE_DEFAULT_MMAP_SIZE + "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), +#endif +#ifdef SQLITE_DEFAULT_PAGE_SIZE + "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE), +#endif +#ifdef SQLITE_DEFAULT_PCACHE_INITSZ + "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ), +#endif +#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS + "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS), +#endif +#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS + "DEFAULT_RECURSIVE_TRIGGERS", +#endif +#ifdef SQLITE_DEFAULT_ROWEST + "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST), +#endif +#ifdef SQLITE_DEFAULT_SECTOR_SIZE + "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE), +#endif +#ifdef SQLITE_DEFAULT_SYNCHRONOUS + "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS), +#endif +#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT + "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT), +#endif +#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS + "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS), +#endif +#ifdef SQLITE_DEFAULT_WORKER_THREADS + "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS), +#endif +#if SQLITE_DIRECT_OVERFLOW_READ + "DIRECT_OVERFLOW_READ", +#endif +#if SQLITE_DISABLE_DIRSYNC + "DISABLE_DIRSYNC", +#endif +#if SQLITE_DISABLE_FTS3_UNICODE + "DISABLE_FTS3_UNICODE", +#endif +#if SQLITE_DISABLE_FTS4_DEFERRED + "DISABLE_FTS4_DEFERRED", +#endif +#if SQLITE_DISABLE_INTRINSIC + "DISABLE_INTRINSIC", +#endif +#if SQLITE_DISABLE_LFS + "DISABLE_LFS", +#endif +#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS + "DISABLE_PAGECACHE_OVERFLOW_STATS", +#endif +#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT + "DISABLE_SKIPAHEAD_DISTINCT", +#endif +#ifdef SQLITE_ENABLE_8_3_NAMES + "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), +#endif +#if SQLITE_ENABLE_API_ARMOR + "ENABLE_API_ARMOR", +#endif +#if SQLITE_ENABLE_ATOMIC_WRITE + "ENABLE_ATOMIC_WRITE", +#endif +#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE + "ENABLE_BATCH_ATOMIC_WRITE", +#endif +#if SQLITE_ENABLE_CEROD + "ENABLE_CEROD", +#endif +#if SQLITE_ENABLE_COLUMN_METADATA + "ENABLE_COLUMN_METADATA", +#endif +#if SQLITE_ENABLE_COLUMN_USED_MASK + "ENABLE_COLUMN_USED_MASK", +#endif +#if SQLITE_ENABLE_COSTMULT + "ENABLE_COSTMULT", +#endif +#if SQLITE_ENABLE_CURSOR_HINTS + "ENABLE_CURSOR_HINTS", +#endif +#if SQLITE_ENABLE_DBSTAT_VTAB + "ENABLE_DBSTAT_VTAB", +#endif +#if SQLITE_ENABLE_EXPENSIVE_ASSERT + "ENABLE_EXPENSIVE_ASSERT", +#endif +#if SQLITE_ENABLE_FTS1 + "ENABLE_FTS1", +#endif +#if SQLITE_ENABLE_FTS2 + "ENABLE_FTS2", +#endif +#if SQLITE_ENABLE_FTS3 + "ENABLE_FTS3", +#endif +#if SQLITE_ENABLE_FTS3_PARENTHESIS + "ENABLE_FTS3_PARENTHESIS", +#endif +#if SQLITE_ENABLE_FTS3_TOKENIZER + "ENABLE_FTS3_TOKENIZER", +#endif +#if SQLITE_ENABLE_FTS4 + "ENABLE_FTS4", +#endif +#if SQLITE_ENABLE_FTS5 + "ENABLE_FTS5", +#endif +#if SQLITE_ENABLE_HIDDEN_COLUMNS + "ENABLE_HIDDEN_COLUMNS", +#endif +#if SQLITE_ENABLE_ICU + "ENABLE_ICU", +#endif +#if SQLITE_ENABLE_IOTRACE + "ENABLE_IOTRACE", +#endif +#if SQLITE_ENABLE_JSON1 + "ENABLE_JSON1", +#endif +#if SQLITE_ENABLE_LOAD_EXTENSION + "ENABLE_LOAD_EXTENSION", +#endif +#ifdef SQLITE_ENABLE_LOCKING_STYLE + "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), +#endif +#if SQLITE_ENABLE_MEMORY_MANAGEMENT + "ENABLE_MEMORY_MANAGEMENT", +#endif +#if SQLITE_ENABLE_MEMSYS3 + "ENABLE_MEMSYS3", +#endif +#if SQLITE_ENABLE_MEMSYS5 + "ENABLE_MEMSYS5", +#endif +#if SQLITE_ENABLE_MULTIPLEX + "ENABLE_MULTIPLEX", +#endif +#if SQLITE_ENABLE_NULL_TRIM + "ENABLE_NULL_TRIM", +#endif +#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK + "ENABLE_OVERSIZE_CELL_CHECK", +#endif +#if SQLITE_ENABLE_PREUPDATE_HOOK + "ENABLE_PREUPDATE_HOOK", +#endif +#if SQLITE_ENABLE_QPSG + "ENABLE_QPSG", +#endif +#if SQLITE_ENABLE_RBU + "ENABLE_RBU", +#endif +#if SQLITE_ENABLE_RTREE + "ENABLE_RTREE", +#endif +#if SQLITE_ENABLE_SELECTTRACE + "ENABLE_SELECTTRACE", +#endif +#if SQLITE_ENABLE_SESSION + "ENABLE_SESSION", +#endif +#if SQLITE_ENABLE_SNAPSHOT + "ENABLE_SNAPSHOT", +#endif +#if SQLITE_ENABLE_SQLLOG + "ENABLE_SQLLOG", +#endif +#if defined(SQLITE_ENABLE_STAT4) + "ENABLE_STAT4", +#elif defined(SQLITE_ENABLE_STAT3) + "ENABLE_STAT3", +#endif +#if SQLITE_ENABLE_STMTVTAB + "ENABLE_STMTVTAB", +#endif +#if SQLITE_ENABLE_STMT_SCANSTATUS + "ENABLE_STMT_SCANSTATUS", +#endif +#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION + "ENABLE_UNKNOWN_SQL_FUNCTION", +#endif +#if SQLITE_ENABLE_UNLOCK_NOTIFY + "ENABLE_UNLOCK_NOTIFY", +#endif +#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT + "ENABLE_UPDATE_DELETE_LIMIT", +#endif +#if SQLITE_ENABLE_URI_00_ERROR + "ENABLE_URI_00_ERROR", +#endif +#if SQLITE_ENABLE_VFSTRACE + "ENABLE_VFSTRACE", +#endif +#if SQLITE_ENABLE_WHERETRACE + "ENABLE_WHERETRACE", +#endif +#if SQLITE_ENABLE_ZIPVFS + "ENABLE_ZIPVFS", +#endif +#if SQLITE_EXPLAIN_ESTIMATED_ROWS + "EXPLAIN_ESTIMATED_ROWS", +#endif +#if SQLITE_EXTRA_IFNULLROW + "EXTRA_IFNULLROW", +#endif +#ifdef SQLITE_EXTRA_INIT + "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT), +#endif +#ifdef SQLITE_EXTRA_SHUTDOWN + "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN), +#endif +#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH + "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH), +#endif +#if SQLITE_FTS5_ENABLE_TEST_MI + "FTS5_ENABLE_TEST_MI", +#endif +#if SQLITE_FTS5_NO_WITHOUT_ROWID + "FTS5_NO_WITHOUT_ROWID", +#endif +#if SQLITE_HAS_CODEC + "HAS_CODEC", +#endif +#if HAVE_ISNAN || SQLITE_HAVE_ISNAN + "HAVE_ISNAN", +#endif +#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX + "HOMEGROWN_RECURSIVE_MUTEX", +#endif +#if SQLITE_IGNORE_AFP_LOCK_ERRORS + "IGNORE_AFP_LOCK_ERRORS", +#endif +#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS + "IGNORE_FLOCK_LOCK_ERRORS", +#endif +#if SQLITE_INLINE_MEMCPY + "INLINE_MEMCPY", +#endif +#if SQLITE_INT64_TYPE + "INT64_TYPE", +#endif +#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX + "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), +#endif +#if SQLITE_LIKE_DOESNT_MATCH_BLOBS + "LIKE_DOESNT_MATCH_BLOBS", +#endif +#if SQLITE_LOCK_TRACE + "LOCK_TRACE", +#endif +#if SQLITE_LOG_CACHE_SPILL + "LOG_CACHE_SPILL", +#endif +#ifdef SQLITE_MALLOC_SOFT_LIMIT + "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT), +#endif +#ifdef SQLITE_MAX_ATTACHED + "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED), +#endif +#ifdef SQLITE_MAX_COLUMN + "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN), +#endif +#ifdef SQLITE_MAX_COMPOUND_SELECT + "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT), +#endif +#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE + "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE), +#endif +#ifdef SQLITE_MAX_EXPR_DEPTH + "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH), +#endif +#ifdef SQLITE_MAX_FUNCTION_ARG + "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG), +#endif +#ifdef SQLITE_MAX_LENGTH + "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH), +#endif +#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH + "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH), +#endif +#ifdef SQLITE_MAX_MEMORY + "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY), +#endif +#ifdef SQLITE_MAX_MMAP_SIZE + "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), +#endif +#ifdef SQLITE_MAX_MMAP_SIZE_ + "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_), +#endif +#ifdef SQLITE_MAX_PAGE_COUNT + "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT), +#endif +#ifdef SQLITE_MAX_PAGE_SIZE + "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE), +#endif +#ifdef SQLITE_MAX_SCHEMA_RETRY + "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), +#endif +#ifdef SQLITE_MAX_SQL_LENGTH + "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH), +#endif +#ifdef SQLITE_MAX_TRIGGER_DEPTH + "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH), +#endif +#ifdef SQLITE_MAX_VARIABLE_NUMBER + "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER), +#endif +#ifdef SQLITE_MAX_VDBE_OP + "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP), +#endif +#ifdef SQLITE_MAX_WORKER_THREADS + "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS), +#endif +#if SQLITE_MEMDEBUG + "MEMDEBUG", +#endif +#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT + "MIXED_ENDIAN_64BIT_FLOAT", +#endif +#if SQLITE_MMAP_READWRITE + "MMAP_READWRITE", +#endif +#if SQLITE_MUTEX_NOOP + "MUTEX_NOOP", +#endif +#if SQLITE_MUTEX_NREF + "MUTEX_NREF", +#endif +#if SQLITE_MUTEX_OMIT + "MUTEX_OMIT", +#endif +#if SQLITE_MUTEX_PTHREADS + "MUTEX_PTHREADS", +#endif +#if SQLITE_MUTEX_W32 + "MUTEX_W32", +#endif +#if SQLITE_NEED_ERR_NAME + "NEED_ERR_NAME", +#endif +#if SQLITE_NOINLINE + "NOINLINE", +#endif +#if SQLITE_NO_SYNC + "NO_SYNC", +#endif +#if SQLITE_OMIT_ALTERTABLE + "OMIT_ALTERTABLE", +#endif +#if SQLITE_OMIT_ANALYZE + "OMIT_ANALYZE", +#endif +#if SQLITE_OMIT_ATTACH + "OMIT_ATTACH", +#endif +#if SQLITE_OMIT_AUTHORIZATION + "OMIT_AUTHORIZATION", +#endif +#if SQLITE_OMIT_AUTOINCREMENT + "OMIT_AUTOINCREMENT", +#endif +#if SQLITE_OMIT_AUTOINIT + "OMIT_AUTOINIT", +#endif +#if SQLITE_OMIT_AUTOMATIC_INDEX + "OMIT_AUTOMATIC_INDEX", +#endif +#if SQLITE_OMIT_AUTORESET + "OMIT_AUTORESET", +#endif +#if SQLITE_OMIT_AUTOVACUUM + "OMIT_AUTOVACUUM", +#endif +#if SQLITE_OMIT_BETWEEN_OPTIMIZATION + "OMIT_BETWEEN_OPTIMIZATION", +#endif +#if SQLITE_OMIT_BLOB_LITERAL + "OMIT_BLOB_LITERAL", +#endif +#if SQLITE_OMIT_BTREECOUNT + "OMIT_BTREECOUNT", +#endif +#if SQLITE_OMIT_CAST + "OMIT_CAST", +#endif +#if SQLITE_OMIT_CHECK + "OMIT_CHECK", +#endif +#if SQLITE_OMIT_COMPLETE + "OMIT_COMPLETE", +#endif +#if SQLITE_OMIT_COMPOUND_SELECT + "OMIT_COMPOUND_SELECT", +#endif +#if SQLITE_OMIT_CONFLICT_CLAUSE + "OMIT_CONFLICT_CLAUSE", +#endif +#if SQLITE_OMIT_CTE + "OMIT_CTE", +#endif +#if SQLITE_OMIT_DATETIME_FUNCS + "OMIT_DATETIME_FUNCS", +#endif +#if SQLITE_OMIT_DECLTYPE + "OMIT_DECLTYPE", +#endif +#if SQLITE_OMIT_DEPRECATED + "OMIT_DEPRECATED", +#endif +#if SQLITE_OMIT_DISKIO + "OMIT_DISKIO", +#endif +#if SQLITE_OMIT_EXPLAIN + "OMIT_EXPLAIN", +#endif +#if SQLITE_OMIT_FLAG_PRAGMAS + "OMIT_FLAG_PRAGMAS", +#endif +#if SQLITE_OMIT_FLOATING_POINT + "OMIT_FLOATING_POINT", +#endif +#if SQLITE_OMIT_FOREIGN_KEY + "OMIT_FOREIGN_KEY", +#endif +#if SQLITE_OMIT_GET_TABLE + "OMIT_GET_TABLE", +#endif +#if SQLITE_OMIT_HEX_INTEGER + "OMIT_HEX_INTEGER", +#endif +#if SQLITE_OMIT_INCRBLOB + "OMIT_INCRBLOB", +#endif +#if SQLITE_OMIT_INTEGRITY_CHECK + "OMIT_INTEGRITY_CHECK", +#endif +#if SQLITE_OMIT_LIKE_OPTIMIZATION + "OMIT_LIKE_OPTIMIZATION", +#endif +#if SQLITE_OMIT_LOAD_EXTENSION + "OMIT_LOAD_EXTENSION", +#endif +#if SQLITE_OMIT_LOCALTIME + "OMIT_LOCALTIME", +#endif +#if SQLITE_OMIT_LOOKASIDE + "OMIT_LOOKASIDE", +#endif +#if SQLITE_OMIT_MEMORYDB + "OMIT_MEMORYDB", +#endif +#if SQLITE_OMIT_OR_OPTIMIZATION + "OMIT_OR_OPTIMIZATION", +#endif +#if SQLITE_OMIT_PAGER_PRAGMAS + "OMIT_PAGER_PRAGMAS", +#endif +#if SQLITE_OMIT_PARSER_TRACE + "OMIT_PARSER_TRACE", +#endif +#if SQLITE_OMIT_POPEN + "OMIT_POPEN", +#endif +#if SQLITE_OMIT_PRAGMA + "OMIT_PRAGMA", +#endif +#if SQLITE_OMIT_PROGRESS_CALLBACK + "OMIT_PROGRESS_CALLBACK", +#endif +#if SQLITE_OMIT_QUICKBALANCE + "OMIT_QUICKBALANCE", +#endif +#if SQLITE_OMIT_REINDEX + "OMIT_REINDEX", +#endif +#if SQLITE_OMIT_SCHEMA_PRAGMAS + "OMIT_SCHEMA_PRAGMAS", +#endif +#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + "OMIT_SCHEMA_VERSION_PRAGMAS", +#endif +#if SQLITE_OMIT_SHARED_CACHE + "OMIT_SHARED_CACHE", +#endif +#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES + "OMIT_SHUTDOWN_DIRECTORIES", +#endif +#if SQLITE_OMIT_SUBQUERY + "OMIT_SUBQUERY", +#endif +#if SQLITE_OMIT_TCL_VARIABLE + "OMIT_TCL_VARIABLE", +#endif +#if SQLITE_OMIT_TEMPDB + "OMIT_TEMPDB", +#endif +#if SQLITE_OMIT_TEST_CONTROL + "OMIT_TEST_CONTROL", +#endif +#if SQLITE_OMIT_TRACE + "OMIT_TRACE", +#endif +#if SQLITE_OMIT_TRIGGER + "OMIT_TRIGGER", +#endif +#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION + "OMIT_TRUNCATE_OPTIMIZATION", +#endif +#if SQLITE_OMIT_UTF16 + "OMIT_UTF16", +#endif +#if SQLITE_OMIT_VACUUM + "OMIT_VACUUM", +#endif +#if SQLITE_OMIT_VIEW + "OMIT_VIEW", +#endif +#if SQLITE_OMIT_VIRTUALTABLE + "OMIT_VIRTUALTABLE", +#endif +#if SQLITE_OMIT_WAL + "OMIT_WAL", +#endif +#if SQLITE_OMIT_WSD + "OMIT_WSD", +#endif +#if SQLITE_OMIT_XFER_OPT + "OMIT_XFER_OPT", +#endif +#if SQLITE_PCACHE_SEPARATE_HEADER + "PCACHE_SEPARATE_HEADER", +#endif +#if SQLITE_PERFORMANCE_TRACE + "PERFORMANCE_TRACE", +#endif +#if SQLITE_POWERSAFE_OVERWRITE + "POWERSAFE_OVERWRITE", +#endif +#if SQLITE_PREFER_PROXY_LOCKING + "PREFER_PROXY_LOCKING", +#endif +#if SQLITE_PROXY_DEBUG + "PROXY_DEBUG", +#endif +#if SQLITE_REVERSE_UNORDERED_SELECTS + "REVERSE_UNORDERED_SELECTS", +#endif +#if SQLITE_RTREE_INT_ONLY + "RTREE_INT_ONLY", +#endif +#if SQLITE_SECURE_DELETE + "SECURE_DELETE", +#endif +#if SQLITE_SMALL_STACK + "SMALL_STACK", +#endif +#ifdef SQLITE_SORTER_PMASZ + "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ), +#endif +#if SQLITE_SOUNDEX + "SOUNDEX", +#endif +#ifdef SQLITE_STAT4_SAMPLES + "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES), +#endif +#ifdef SQLITE_STMTJRNL_SPILL + "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL), +#endif +#if SQLITE_SUBSTR_COMPATIBILITY + "SUBSTR_COMPATIBILITY", +#endif +#if SQLITE_SYSTEM_MALLOC + "SYSTEM_MALLOC", +#endif +#if SQLITE_TCL + "TCL", +#endif +#ifdef SQLITE_TEMP_STORE + "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), +#endif +#if SQLITE_TEST + "TEST", +#endif +#if defined(SQLITE_THREADSAFE) + "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), +#elif defined(THREADSAFE) + "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE), +#else + "THREADSAFE=1", +#endif +#if SQLITE_UNLINK_AFTER_CLOSE + "UNLINK_AFTER_CLOSE", +#endif +#if SQLITE_UNTESTABLE + "UNTESTABLE", +#endif +#if SQLITE_USER_AUTHENTICATION + "USER_AUTHENTICATION", +#endif +#if SQLITE_USE_ALLOCA + "USE_ALLOCA", +#endif +#if SQLITE_USE_FCNTL_TRACE + "USE_FCNTL_TRACE", +#endif +#if SQLITE_USE_URI + "USE_URI", +#endif +#if SQLITE_VDBE_COVERAGE + "VDBE_COVERAGE", +#endif +#if SQLITE_WIN32_MALLOC + "WIN32_MALLOC", +#endif +#if SQLITE_ZERO_MALLOC + "ZERO_MALLOC", +#endif +/* +** END CODE GENERATED BY tool/mkctime.tcl +*/ +}; + +SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){ + *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); + return (const char**)sqlite3azCompileOpt; +} + +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ + +/************** End of ctime.c ***********************************************/ /************** Begin file sqliteInt.h ***************************************/ /* ** 2001 September 15 @@ -76,14 +831,6 @@ #endif /* -** Make sure that rand_s() is available on Windows systems with MSVC 2005 -** or higher. -*/ -#if defined(_MSC_VER) && _MSC_VER>=1400 -# define _CRT_RAND_S -#endif - -/* ** Include the header file used to customize the compiler options for MSVC. ** This should be done first so that it can successfully prevent spurious ** compiler warnings due to subsequent content in this file and other files @@ -276,7 +1023,7 @@ /************** Include sqlite3.h in the middle of sqliteInt.h ***************/ /************** Begin file sqlite3.h *****************************************/ /* -** 2001 September 15 +** 2001-09-15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -392,15 +1139,17 @@ extern "C" { ** a string which identifies a particular check-in of SQLite ** within its configuration management system. ^The SQLITE_SOURCE_ID ** string contains the date and time of the check-in (UTC) and a SHA1 -** or SHA3-256 hash of the entire source tree. +** or SHA3-256 hash of the entire source tree. If the source code has +** been edited in any way since it was last checked in, then the last +** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.19.3" -#define SQLITE_VERSION_NUMBER 3019003 -#define SQLITE_SOURCE_ID "2017-06-08 14:26:16 0ee482a1e0eae22e08edc8978c9733a96603d4509645f348ebf55b579e89636b" +#define SQLITE_VERSION "3.21.0" +#define SQLITE_VERSION_NUMBER 3021000 +#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -416,7 +1165,7 @@ extern "C" { ** ** <blockquote><pre> ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); -** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 ); +** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 ); ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); ** </pre></blockquote>)^ ** @@ -426,9 +1175,11 @@ extern "C" { ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to -** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns +** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the -** [SQLITE_SOURCE_ID] C preprocessor macro. +** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built +** using an edited copy of [the amalgamation], then the last four characters +** of the hash might be different from [SQLITE_SOURCE_ID].)^ ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ @@ -694,7 +1445,7 @@ SQLITE_API int sqlite3_exec( */ #define SQLITE_OK 0 /* Successful result */ /* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_ERROR 1 /* Generic error */ #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ @@ -709,7 +1460,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_EMPTY 16 /* Internal use only */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ #define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ @@ -717,7 +1468,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_FORMAT 24 /* Not used */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ @@ -771,6 +1522,9 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) +#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) +#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) +#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) @@ -857,6 +1611,11 @@ SQLITE_API int sqlite3_exec( ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on ** read-only media and cannot be changed even by processes with ** elevated privileges. +** +** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying +** filesystem supports doing multiple write operations atomically when those +** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and +** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 @@ -872,6 +1631,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_IMMUTABLE 0x00002000 +#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 /* ** CAPI3REF: File Locking Levels @@ -1006,6 +1766,7 @@ struct sqlite3_file { ** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] ** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE] ** <li> [SQLITE_IOCAP_IMMUTABLE] +** <li> [SQLITE_IOCAP_BATCH_ATOMIC] ** </ul> ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of @@ -1289,6 +2050,40 @@ struct sqlite3_io_methods { ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for ** this opcode. +** +** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]] +** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then +** the file descriptor is placed in "batch write mode", which +** means all subsequent write operations will be deferred and done +** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems +** that do not support batch atomic writes will return SQLITE_NOTFOUND. +** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to +** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or +** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make +** no VFS interface calls on the same [sqlite3_file] file descriptor +** except for calls to the xWrite method and the xFileControl method +** with [SQLITE_FCNTL_SIZE_HINT]. +** +** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]] +** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write +** operations since the previous successful call to +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically. +** This file control returns [SQLITE_OK] if and only if the writes were +** all performed successfully and have been committed to persistent storage. +** ^Regardless of whether or not it is successful, this file control takes +** the file descriptor out of batch write mode so that all subsequent +** write operations are independent. +** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]] +** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write +** operations since the previous successful call to +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. +** ^This file control takes the file descriptor out of batch write mode +** so that all subsequent write operations are independent. +** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1320,6 +2115,9 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_JOURNAL_POINTER 28 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 #define SQLITE_FCNTL_PDB 30 +#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 +#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 +#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1890,6 +2688,16 @@ struct sqlite3_mem_methods { ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** +** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> +** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of +** type int, interpreted as a boolean, which if true provides a hint to +** SQLite that it should avoid large memory allocations if possible. +** SQLite will run faster if it is free to make large memory allocations, +** but some application might prefer to run slower in exchange for +** guarantees about memory fragmentation that are possible if large +** allocations are avoided. This hint is normally off. +** </dd> +** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of @@ -1907,25 +2715,7 @@ struct sqlite3_mem_methods { ** </dd> ** ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt> -** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer -** that SQLite can use for scratch memory. ^(There are three arguments -** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte -** aligned memory buffer from which the scratch allocations will be -** drawn, the size of each scratch allocation (sz), -** and the maximum number of scratch allocations (N).)^ -** The first argument must be a pointer to an 8-byte aligned buffer -** of at least sz*N bytes of memory. -** ^SQLite will not use more than one scratch buffers per thread. -** ^SQLite will never request a scratch buffer that is more than 6 -** times the database page size. -** ^If SQLite needs needs additional -** scratch memory beyond what is provided by this configuration option, then -** [sqlite3_malloc()] will be used to obtain the memory needed.<p> -** ^When the application provides any amount of scratch memory using -** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large -** [sqlite3_malloc|heap allocations]. -** This can help [Robson proof|prevent memory allocation failures] due to heap -** fragmentation in low-memory embedded systems. +** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used. ** </dd> ** ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> @@ -1961,8 +2751,7 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and -** [SQLITE_CONFIG_PAGECACHE]. +** beyond those provided for by [SQLITE_CONFIG_PAGECACHE]. ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns ** [SQLITE_ERROR] if invoked otherwise. @@ -2155,7 +2944,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ -#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */ #define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ #define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ @@ -2176,6 +2965,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ +#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ /* ** CAPI3REF: Database Connection Configuration Options @@ -2284,6 +3074,17 @@ struct sqlite3_mem_methods { ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** +** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> +** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates +** the [query planner stability guarantee] (QPSG). When the QPSG is active, +** a single SQL query statement will always use the same algorithm regardless +** of values of [bound parameters].)^ The QPSG disables some query optimizations +** that look at the values of bound parameters, which can make some queries +** slower. But the QPSG has the advantage of more predictable behavior. With +** the QPSG active, SQLite will always use the same query plan in the field as +** was used during testing in the lab. +** </dd> +** ** </dl> */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2293,6 +3094,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ /* @@ -2956,7 +3758,8 @@ SQLITE_API void sqlite3_randomness(int N, void *P); ** [database connection], supplied in the first argument. ** ^The authorizer callback is invoked as SQL statements are being compiled ** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various +** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()], +** and [sqlite3_prepare16_v3()]. ^At various ** points during the compilation process, as logic is being created ** to perform various actions, the authorizer callback is invoked to ** see if those actions are allowed. ^The authorizer callback should @@ -3363,10 +4166,10 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** ^If [URI filename] interpretation is enabled, and the filename argument ** begins with "file:", then the filename is interpreted as a URI. ^URI ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is -** set in the fourth argument to sqlite3_open_v2(), or if it has +** set in the third argument to sqlite3_open_v2(), or if it has ** been enabled globally using the [SQLITE_CONFIG_URI] option with the ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. -** As of SQLite version 3.7.7, URI filename interpretation is turned off +** URI filename interpretation is turned off ** by default, but future releases of SQLite might enable URI filename ** interpretation by default. See "[URI filenames]" for additional ** information. @@ -3745,6 +4548,29 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 +/* +** CAPI3REF: Prepare Flags +** +** These constants define various flags that can be passed into +** "prepFlags" parameter of the [sqlite3_prepare_v3()] and +** [sqlite3_prepare16_v3()] interfaces. +** +** New flags may be added in future releases of SQLite. +** +** <dl> +** [[SQLITE_PREPARE_PERSISTENT]] ^(<dt>SQLITE_PREPARE_PERSISTENT</dt> +** <dd>The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner +** that the prepared statement will be retained for a long time and +** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()] +** and [sqlite3_prepare16_v3()] assume that the prepared statement will +** be used just once or at most a few times and then destroyed using +** [sqlite3_finalize()] relatively soon. The current implementation acts +** on this hint by avoiding the use of [lookaside memory] so as not to +** deplete the limited store of lookaside memory. Future versions of +** SQLite may act on this hint differently. +** </dl> +*/ +#define SQLITE_PREPARE_PERSISTENT 0x01 /* ** CAPI3REF: Compiling An SQL Statement @@ -3752,17 +4578,29 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** METHOD: sqlite3 ** CONSTRUCTOR: sqlite3_stmt ** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. +** To execute an SQL statement, it must first be compiled into a byte-code +** program using one of these routines. Or, in other words, these routines +** are constructors for the [prepared statement] object. +** +** The preferred routine to use is [sqlite3_prepare_v2()]. The +** [sqlite3_prepare()] interface is legacy and should be avoided. +** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used +** for special purposes. +** +** The use of the UTF-8 interfaces is preferred, as SQLite currently +** does all parsing using UTF-8. The UTF-16 interfaces are provided +** as a convenience. The UTF-16 interfaces work by converting the +** input text into UTF-8, then invoking the corresponding UTF-8 interface. ** ** The first argument, "db", is a [database connection] obtained from a ** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or ** [sqlite3_open16()]. The database connection must not have been closed. ** ** The second argument, "zSql", is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. +** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(), +** and sqlite3_prepare_v3() +** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(), +** and sqlite3_prepare16_v3() use UTF-16. ** ** ^If the nByte argument is negative, then zSql is read up to the ** first zero terminator. ^If nByte is positive, then it is the @@ -3789,10 +4627,11 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; ** otherwise an [error code] is returned. ** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** ^In the "v2" interfaces, the prepared statement +** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(), +** and sqlite3_prepare16_v3() interfaces are recommended for all new programs. +** The older interfaces (sqlite3_prepare() and sqlite3_prepare16()) +** are retained for backwards compatibility, but their use is discouraged. +** ^In the "vX" interfaces, the prepared statement ** that is returned (the [sqlite3_stmt] object) contains a copy of the ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: @@ -3825,6 +4664,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. ** </li> +** +** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having +** the extra prepFlags parameter, which is a bit array consisting of zero or +** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The +** sqlite3_prepare_v2() interface works exactly the same as +** sqlite3_prepare_v3() with a zero prepFlags parameter. ** </ol> */ SQLITE_API int sqlite3_prepare( @@ -3841,6 +4686,14 @@ SQLITE_API int sqlite3_prepare_v2( sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); +SQLITE_API int sqlite3_prepare_v3( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ @@ -3855,6 +4708,14 @@ SQLITE_API int sqlite3_prepare16_v2( sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); +SQLITE_API int sqlite3_prepare16_v3( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); /* ** CAPI3REF: Retrieving Statement SQL @@ -3862,7 +4723,8 @@ SQLITE_API int sqlite3_prepare16_v2( ** ** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8 ** SQL text used to create [prepared statement] P if P was -** created by either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], +** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** string containing the SQL text of prepared statement P with ** [bound parameters] expanded. @@ -3981,8 +4843,9 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. -** Unprotected sqlite3_value objects may only be used with -** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** Unprotected sqlite3_value objects may only be used as arguments +** to [sqlite3_result_value()], [sqlite3_bind_value()], and +** [sqlite3_value_dup()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. */ @@ -4088,6 +4951,15 @@ typedef struct sqlite3_context sqlite3_context; ** [sqlite3_blob_open | incremental BLOB I/O] routines. ** ^A negative value for the zeroblob results in a zero-length BLOB. ** +** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in +** [prepared statement] S to have an SQL value of NULL, but to also be +** associated with the pointer P of type T. ^D is either a NULL pointer or +** a pointer to a destructor function for P. ^SQLite will invoke the +** destructor D with a single argument of P when it is finished using +** P. The T parameter should be a static string, preferably a string +** literal. The sqlite3_bind_pointer() routine is part of the +** [pointer passing interface] added for SQLite 3.20.0. +** ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer ** for the [prepared statement] or with a prepared statement for which ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], @@ -4121,6 +4993,7 @@ SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*) SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*)); SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); @@ -4164,8 +5037,8 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); ** ^If the value N is out of range or if the N-th parameter is ** nameless, then NULL is returned. ^The returned string is ** always in UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. +** originally specified as UTF-16 in [sqlite3_prepare16()], +** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and @@ -4182,7 +5055,8 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); ** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero ** is returned if no matching parameter is found. ^The parameter ** name must be given in UTF-8 even if the original statement -** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or +** [sqlite3_prepare16_v3()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and @@ -4336,16 +5210,18 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** CAPI3REF: Evaluate An SQL Statement ** METHOD: sqlite3_stmt ** -** After a [prepared statement] has been prepared using either -** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** After a [prepared statement] has been prepared using any of +** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()], +** or [sqlite3_prepare16_v3()] or one of the legacy ** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function ** must be called one or more times to evaluate the statement. ** ** The details of the behavior of the sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy +** on whether the statement was prepared using the newer "vX" interfaces +** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()], +** [sqlite3_prepare16_v2()] or the older legacy +** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "vX" interface is recommended for new applications but the legacy ** interface will continue to be supported. ** ** ^In the legacy interface, the return value will be either [SQLITE_BUSY], @@ -4406,10 +5282,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** specific [error codes] that better describes the error. ** We admit that this is a goofy design. The problem has been fixed ** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()] +** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead ** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, ** then the more specific [error codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. +** by sqlite3_step(). The use of the "vX" interfaces is recommended. */ SQLITE_API int sqlite3_step(sqlite3_stmt*); @@ -4471,6 +5348,28 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** KEYWORDS: {column access functions} ** METHOD: sqlite3_stmt ** +** <b>Summary:</b> +** <blockquote><table border=0 cellpadding=0 cellspacing=0> +** <tr><td><b>sqlite3_column_blob</b><td>→<td>BLOB result +** <tr><td><b>sqlite3_column_double</b><td>→<td>REAL result +** <tr><td><b>sqlite3_column_int</b><td>→<td>32-bit INTEGER result +** <tr><td><b>sqlite3_column_int64</b><td>→<td>64-bit INTEGER result +** <tr><td><b>sqlite3_column_text</b><td>→<td>UTF-8 TEXT result +** <tr><td><b>sqlite3_column_text16</b><td>→<td>UTF-16 TEXT result +** <tr><td><b>sqlite3_column_value</b><td>→<td>The result as an +** [sqlite3_value|unprotected sqlite3_value] object. +** <tr><td> <td> <td> +** <tr><td><b>sqlite3_column_bytes</b><td>→<td>Size of a BLOB +** or a UTF-8 TEXT result in bytes +** <tr><td><b>sqlite3_column_bytes16 </b> +** <td>→ <td>Size of UTF-16 +** TEXT in bytes +** <tr><td><b>sqlite3_column_type</b><td>→<td>Default +** datatype of the result +** </table></blockquote> +** +** <b>Details:</b> +** ** ^These routines return information about a single column of the current ** result row of a query. ^In every case the first argument is a pointer ** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] @@ -4492,16 +5391,29 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** are called from a different thread while any of these routines ** are pending, then the results are undefined. ** +** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16) +** each return the value of a result column in a specific data format. If +** the result column is not initially in the requested format (for example, +** if the query returns an integer but the sqlite3_column_text() interface +** is used to extract the value) then an automatic type conversion is performed. +** ** ^The sqlite3_column_type() routine returns the ** [SQLITE_INTEGER | datatype code] for the initial data type ** of the result column. ^The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. +** The return value of sqlite3_column_type() can be used to decide which +** of the first six interface should be used to extract the column value. +** The value returned by sqlite3_column_type() is only meaningful if no +** automatic type conversions have occurred for the value in question. +** After a type conversion, the result of calling sqlite3_column_type() +** is undefined, though harmless. Future ** versions of SQLite may change the behavior of sqlite3_column_type() ** following a type conversion. ** +** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes() +** or sqlite3_column_bytes16() interfaces can be used to determine the size +** of that BLOB or string. +** ** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() ** routine returns the number of bytes in that BLOB or string. ** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts @@ -4538,9 +5450,13 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [sqlite3_column_value()] is used in any other way, including calls ** to routines like [sqlite3_value_int()], [sqlite3_value_text()], ** or [sqlite3_value_bytes()], the behavior is not threadsafe. +** Hence, the sqlite3_column_value() interface +** is normally only useful within the implementation of +** [application-defined SQL functions] or [virtual tables], not within +** top-level application code. ** -** These routines attempt to convert the value where appropriate. ^For -** example, if the internal representation is FLOAT and a text result +** The these routines may attempt to convert the datatype of the result. +** ^For example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to perform the ** conversion automatically. ^(The following table details the conversions ** that are applied: @@ -4612,7 +5528,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** ^The pointers returned are valid until a type conversion occurs as ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or ** [sqlite3_finalize()] is called. ^The memory space used to hold strings -** and BLOBs is freed automatically. Do <em>not</em> pass the pointers returned +** and BLOBs is freed automatically. Do not pass the pointers returned ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** [sqlite3_free()]. ** @@ -4623,15 +5539,15 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [SQLITE_NOMEM].)^ */ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object @@ -4865,21 +5781,40 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** CAPI3REF: Obtaining SQL Values ** METHOD: sqlite3_value ** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 3rd parameter to these callbacks is an array of pointers to -** [protected sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. +** <b>Summary:</b> +** <blockquote><table border=0 cellpadding=0 cellspacing=0> +** <tr><td><b>sqlite3_value_blob</b><td>→<td>BLOB value +** <tr><td><b>sqlite3_value_double</b><td>→<td>REAL value +** <tr><td><b>sqlite3_value_int</b><td>→<td>32-bit INTEGER value +** <tr><td><b>sqlite3_value_int64</b><td>→<td>64-bit INTEGER value +** <tr><td><b>sqlite3_value_pointer</b><td>→<td>Pointer value +** <tr><td><b>sqlite3_value_text</b><td>→<td>UTF-8 TEXT value +** <tr><td><b>sqlite3_value_text16</b><td>→<td>UTF-16 TEXT value in +** the native byteorder +** <tr><td><b>sqlite3_value_text16be</b><td>→<td>UTF-16be TEXT value +** <tr><td><b>sqlite3_value_text16le</b><td>→<td>UTF-16le TEXT value +** <tr><td> <td> <td> +** <tr><td><b>sqlite3_value_bytes</b><td>→<td>Size of a BLOB +** or a UTF-8 TEXT in bytes +** <tr><td><b>sqlite3_value_bytes16 </b> +** <td>→ <td>Size of UTF-16 +** TEXT in bytes +** <tr><td><b>sqlite3_value_type</b><td>→<td>Default +** datatype of the value +** <tr><td><b>sqlite3_value_numeric_type </b> +** <td>→ <td>Best numeric datatype of the value +** </table></blockquote> +** +** <b>Details:</b> +** +** These routines extract type, size, and content information from +** [protected sqlite3_value] objects. Protected sqlite3_value objects +** are used to pass parameter information into implementation of +** [application-defined SQL functions] and [virtual tables]. ** ** These routines work only with [protected sqlite3_value] objects. ** Any attempt to use these routines on an [unprotected sqlite3_value] -** object results in undefined behavior. +** is not threadsafe. ** ** ^These routines work just like the corresponding [column access functions] ** except that these routines take a single [protected sqlite3_value] object @@ -4890,6 +5825,24 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces ** extract UTF-16 strings as big-endian and little-endian respectively. ** +** ^If [sqlite3_value] object V was initialized +** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)] +** and if X and Y are strings that compare equal according to strcmp(X,Y), +** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise, +** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer() +** routine is part of the [pointer passing interface] added for SQLite 3.20.0. +** +** ^(The sqlite3_value_type(V) interface returns the +** [SQLITE_INTEGER | datatype code] for the initial datatype of the +** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^ +** Other interfaces might change the datatype for an sqlite3_value object. +** For example, if the datatype is initially SQLITE_INTEGER and +** sqlite3_value_text(V) is called to extract a text value for that +** integer, then subsequent calls to sqlite3_value_type(V) might return +** SQLITE_TEXT. Whether or not a persistent internal datatype conversion +** occurs is undefined and may change from one release of SQLite to the next. +** ** ^(The sqlite3_value_numeric_type() interface attempts to apply ** numeric affinity to the value. This means that an attempt is ** made to convert the value to an integer or floating point. If @@ -4908,15 +5861,16 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** the SQL function that supplied the [sqlite3_value*] parameters. */ SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API double sqlite3_value_double(sqlite3_value*); SQLITE_API int sqlite3_value_int(sqlite3_value*); SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*); SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); @@ -4929,10 +5883,6 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. -** -** SQLite makes no use of subtype itself. It merely passes the subtype -** from the result of one [application-defined SQL function] into the -** input of another. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -5202,7 +6152,7 @@ typedef void (*sqlite3_destructor_type)(void*); ** when it has finished using that result. ** ^If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from +** then SQLite makes a copy of the result into space obtained ** from [sqlite3_malloc()] before it returns. ** ** ^The sqlite3_result_value() interface sets the result of @@ -5215,6 +6165,17 @@ typedef void (*sqlite3_destructor_type)(void*); ** [unprotected sqlite3_value] object is required, so either ** kind of [sqlite3_value] object can be used with this interface. ** +** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an +** SQL NULL value, just like [sqlite3_result_null(C)], except that it +** also associates the host-language pointer P or type T with that +** NULL value such that the pointer can be retrieved within an +** [application-defined SQL function] using [sqlite3_value_pointer()]. +** ^If the D parameter is not NULL, then it is a pointer to a destructor +** for the P parameter. ^SQLite invokes D with P as its only argument +** when SQLite is finished with P. The T parameter should be a static +** string and preferably a string literal. The sqlite3_result_pointer() +** routine is part of the [pointer passing interface] added for SQLite 3.20.0. +** ** If these routines are called from within the different thread ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. @@ -5238,6 +6199,7 @@ SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(* SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*)); SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); @@ -5897,7 +6859,9 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it -** does not. +** does not. If the table name parameter T in a call to +** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is +** undefined behavior. ** ** ^The column is identified by the second, third and fourth parameters to ** this function. ^(The second parameter is either the name of the database @@ -6307,15 +7271,20 @@ struct sqlite3_index_info { ** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. */ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_NE 68 +#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 +#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 +#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 +#define SQLITE_INDEX_CONSTRAINT_IS 72 /* ** CAPI3REF: Register A Virtual Table Implementation @@ -7067,7 +8036,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 -#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 @@ -7126,8 +8095,7 @@ SQLITE_API int sqlite3_status64( ** <dd>This parameter is the current amount of memory checked out ** using [sqlite3_malloc()], either directly or indirectly. The ** figure includes calls made to [sqlite3_malloc()] by the application -** and internal memory usage by the SQLite library. Scratch memory -** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** and internal memory usage by the SQLite library. Auxiliary page-cache ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in ** this parameter. The amount returned is the sum of the allocation ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^ @@ -7165,29 +8133,14 @@ SQLITE_API int sqlite3_status64( ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.</dd>)^ ** -** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt> -** <dd>This parameter returns the number of allocations used out of the -** [scratch memory allocator] configured using -** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not -** in bytes. Since a single thread may only have one scratch allocation -** outstanding at time, this parameter also reports the number of threads -** using scratch memory at the same time.</dd>)^ +** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt> +** <dd>No longer used.</dd> ** ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt> -** <dd>This parameter returns the number of bytes of scratch memory -** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] -** buffer and where forced to overflow to [sqlite3_malloc()]. The values -** returned include overflows because the requested allocation was too -** larger (that is, because the requested allocation was larger than the -** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer -** slots were available. -** </dd>)^ -** -** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt> -** <dd>This parameter records the largest memory allocation request -** handed to [scratch memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.</dd>)^ +** <dd>No longer used.</dd> +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt> +** <dd>No longer used.</dd> ** ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt> ** <dd>The *pHighwater parameter records the deepest parser stack. @@ -7200,12 +8153,12 @@ SQLITE_API int sqlite3_status64( #define SQLITE_STATUS_MEMORY_USED 0 #define SQLITE_STATUS_PAGECACHE_USED 1 #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 -#define SQLITE_STATUS_SCRATCH_USED 3 -#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ #define SQLITE_STATUS_MALLOC_SIZE 5 #define SQLITE_STATUS_PARSER_STACK 6 #define SQLITE_STATUS_PAGECACHE_SIZE 7 -#define SQLITE_STATUS_SCRATCH_SIZE 8 +#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ #define SQLITE_STATUS_MALLOC_COUNT 9 /* @@ -7410,6 +8363,24 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** used as a proxy for the total work done by the prepared statement. ** If the number of virtual machine operations exceeds 2147483647 ** then the value returned by this statement status code is undefined. +** +** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt> +** <dd>^This is the number of times that the prepare statement has been +** automatically regenerated due to schema changes or change to +** [bound parameters] that might affect the query plan. +** +** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> +** <dd>^This is the number of times that the prepared statement has +** been run. A single "run" for the purposes of this counter is one +** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. +** The counter is incremented on the first [sqlite3_step()] call of each +** cycle. +** +** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> +** <dd>^This is the approximate number of bytes of heap memory +** used to store the prepared statement. ^This value is not actually +** a counter, and so the resetFlg parameter to sqlite3_stmt_status() +** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ @@ -7417,6 +8388,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 +#define SQLITE_STMTSTATUS_REPREPARE 5 +#define SQLITE_STMTSTATUS_RUN 6 +#define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object @@ -9281,8 +10255,8 @@ SQLITE_API int sqlite3session_diff( */ SQLITE_API int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ - int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ - void **ppPatchset /* OUT: Buffer containing changeset */ + int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ + void **ppPatchset /* OUT: Buffer containing patchset */ ); /* @@ -10049,12 +11023,12 @@ SQLITE_API int sqlite3changeset_apply( ** ** <table border=1 style="margin-left:8ex;margin-right:8ex"> ** <tr><th>Streaming function<th>Non-streaming equivalent</th> -** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply] -** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat] -** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert] -** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start] -** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset] -** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset] +** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] +** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat] +** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert] +** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start] +** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset] +** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset] ** </table> ** ** Non-streaming functions that accept changesets (or patchsets) as input @@ -10783,8 +11757,9 @@ struct fts5_api { ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build */ -#ifdef _HAVE_SQLITE_CONFIG_H -#include "config.h" +#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H) +/* #include "config.h" */ +#define SQLITECONFIG_H 1 #endif /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ @@ -11094,6 +12069,11 @@ struct fts5_api { ** ** Older versions of SQLite used an optional THREADSAFE macro. ** We support that for legacy. +** +** To ensure that the correct value of "THREADSAFE" is reported when querying +** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this +** logic is partially replicated in ctime.c. If it is updated here, it should +** also be updated there. */ #if !defined(SQLITE_THREADSAFE) # if defined(THREADSAFE) @@ -11269,6 +12249,21 @@ SQLITE_PRIVATE void sqlite3Coverage(int); #endif /* +** Some conditionals are optimizations only. In other words, if the +** conditionals are replaced with a constant 1 (true) or 0 (false) then +** the correct answer is still obtained, though perhaps not as quickly. +** +** The following macros mark these optimizations conditionals. +*/ +#if defined(SQLITE_MUTATION_TEST) +# define OK_IF_ALWAYS_TRUE(X) (1) +# define OK_IF_ALWAYS_FALSE(X) (0) +#else +# define OK_IF_ALWAYS_TRUE(X) (X) +# define OK_IF_ALWAYS_FALSE(X) (X) +#endif + +/* ** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is ** defined. We need to defend against those failures when testing with ** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches @@ -11462,63 +12457,63 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_AS 24 #define TK_WITHOUT 25 #define TK_COMMA 26 -#define TK_ID 27 -#define TK_ABORT 28 -#define TK_ACTION 29 -#define TK_AFTER 30 -#define TK_ANALYZE 31 -#define TK_ASC 32 -#define TK_ATTACH 33 -#define TK_BEFORE 34 -#define TK_BY 35 -#define TK_CASCADE 36 -#define TK_CAST 37 -#define TK_COLUMNKW 38 -#define TK_CONFLICT 39 -#define TK_DATABASE 40 -#define TK_DESC 41 -#define TK_DETACH 42 -#define TK_EACH 43 -#define TK_FAIL 44 -#define TK_FOR 45 -#define TK_IGNORE 46 -#define TK_INITIALLY 47 -#define TK_INSTEAD 48 -#define TK_LIKE_KW 49 -#define TK_MATCH 50 -#define TK_NO 51 -#define TK_KEY 52 -#define TK_OF 53 -#define TK_OFFSET 54 -#define TK_PRAGMA 55 -#define TK_RAISE 56 -#define TK_RECURSIVE 57 -#define TK_REPLACE 58 -#define TK_RESTRICT 59 -#define TK_ROW 60 -#define TK_TRIGGER 61 -#define TK_VACUUM 62 -#define TK_VIEW 63 -#define TK_VIRTUAL 64 -#define TK_WITH 65 -#define TK_REINDEX 66 -#define TK_RENAME 67 -#define TK_CTIME_KW 68 -#define TK_ANY 69 -#define TK_OR 70 -#define TK_AND 71 -#define TK_IS 72 -#define TK_BETWEEN 73 -#define TK_IN 74 -#define TK_ISNULL 75 -#define TK_NOTNULL 76 -#define TK_NE 77 -#define TK_EQ 78 -#define TK_GT 79 -#define TK_LE 80 -#define TK_LT 81 -#define TK_GE 82 -#define TK_ESCAPE 83 +#define TK_ABORT 27 +#define TK_ACTION 28 +#define TK_AFTER 29 +#define TK_ANALYZE 30 +#define TK_ASC 31 +#define TK_ATTACH 32 +#define TK_BEFORE 33 +#define TK_BY 34 +#define TK_CASCADE 35 +#define TK_CAST 36 +#define TK_CONFLICT 37 +#define TK_DATABASE 38 +#define TK_DESC 39 +#define TK_DETACH 40 +#define TK_EACH 41 +#define TK_FAIL 42 +#define TK_OR 43 +#define TK_AND 44 +#define TK_IS 45 +#define TK_MATCH 46 +#define TK_LIKE_KW 47 +#define TK_BETWEEN 48 +#define TK_IN 49 +#define TK_ISNULL 50 +#define TK_NOTNULL 51 +#define TK_NE 52 +#define TK_EQ 53 +#define TK_GT 54 +#define TK_LE 55 +#define TK_LT 56 +#define TK_GE 57 +#define TK_ESCAPE 58 +#define TK_ID 59 +#define TK_COLUMNKW 60 +#define TK_FOR 61 +#define TK_IGNORE 62 +#define TK_INITIALLY 63 +#define TK_INSTEAD 64 +#define TK_NO 65 +#define TK_KEY 66 +#define TK_OF 67 +#define TK_OFFSET 68 +#define TK_PRAGMA 69 +#define TK_RAISE 70 +#define TK_RECURSIVE 71 +#define TK_REPLACE 72 +#define TK_RESTRICT 73 +#define TK_ROW 74 +#define TK_TRIGGER 75 +#define TK_VACUUM 76 +#define TK_VIEW 77 +#define TK_VIRTUAL 78 +#define TK_WITH 79 +#define TK_REINDEX 80 +#define TK_RENAME 81 +#define TK_CTIME_KW 82 +#define TK_ANY 83 #define TK_BITAND 84 #define TK_BITOR 85 #define TK_LSHIFT 86 @@ -11578,28 +12573,23 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_INDEX 140 #define TK_ALTER 141 #define TK_ADD 142 -#define TK_TO_TEXT 143 -#define TK_TO_BLOB 144 -#define TK_TO_NUMERIC 145 -#define TK_TO_INT 146 -#define TK_TO_REAL 147 -#define TK_ISNOT 148 -#define TK_END_OF_FILE 149 -#define TK_UNCLOSED_STRING 150 -#define TK_FUNCTION 151 -#define TK_COLUMN 152 -#define TK_AGG_FUNCTION 153 -#define TK_AGG_COLUMN 154 -#define TK_UMINUS 155 -#define TK_UPLUS 156 -#define TK_REGISTER 157 -#define TK_VECTOR 158 -#define TK_SELECT_COLUMN 159 -#define TK_IF_NULL_ROW 160 -#define TK_ASTERISK 161 -#define TK_SPAN 162 -#define TK_SPACE 163 -#define TK_ILLEGAL 164 +#define TK_ISNOT 143 +#define TK_FUNCTION 144 +#define TK_COLUMN 145 +#define TK_AGG_FUNCTION 146 +#define TK_AGG_COLUMN 147 +#define TK_UMINUS 148 +#define TK_UPLUS 149 +#define TK_REGISTER 150 +#define TK_VECTOR 151 +#define TK_SELECT_COLUMN 152 +#define TK_IF_NULL_ROW 153 +#define TK_ASTERISK 154 +#define TK_SPAN 155 +#define TK_END_OF_FILE 156 +#define TK_UNCLOSED_STRING 157 +#define TK_SPACE 158 +#define TK_ILLEGAL 159 /* The token codes above must all fit in 8 bits */ #define TKFLG_MASK 0xff @@ -11684,7 +12674,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 -# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */ #endif /* @@ -11721,6 +12710,15 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #endif /* +** The compile-time options SQLITE_MMAP_READWRITE and +** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another. +** You must choose one or the other (or neither) but not both. +*/ +#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) +#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE +#endif + +/* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ @@ -11985,7 +12983,6 @@ typedef INT16_TYPE LogEst; # else # define SQLITE_MAX_MMAP_SIZE 0 # endif -# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ #endif /* @@ -11995,7 +12992,6 @@ typedef INT16_TYPE LogEst; */ #ifndef SQLITE_DEFAULT_MMAP_SIZE # define SQLITE_DEFAULT_MMAP_SIZE 0 -# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */ #endif #if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE # undef SQLITE_DEFAULT_MMAP_SIZE @@ -12020,7 +13016,7 @@ typedef INT16_TYPE LogEst; ** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not ** the Select query generator tracing logic is turned on. */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE) +#if defined(SQLITE_ENABLE_SELECTTRACE) # define SELECTTRACE_ENABLED 1 #else # define SELECTTRACE_ENABLED 0 @@ -12424,6 +13420,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursor( struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); +SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void); SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); @@ -12480,9 +13477,9 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int flags, int seekResult); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); @@ -12633,7 +13630,7 @@ struct VdbeOp { #ifdef SQLITE_ENABLE_CURSOR_HINTS Expr *pExpr; /* Used when p4type is P4_EXPR */ #endif - int (*xAdvance)(BtCursor *, int *); + int (*xAdvance)(BtCursor *, int); } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS char *zComment; /* Comment to improve readability */ @@ -12677,24 +13674,26 @@ typedef struct VdbeOpList VdbeOpList; /* ** Allowed values of VdbeOp.p4type */ -#define P4_NOTUSED 0 /* The P4 parameter is not used */ -#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ -#define P4_STATIC (-2) /* Pointer to a static string */ -#define P4_COLLSEQ (-3) /* P4 is a pointer to a CollSeq structure */ -#define P4_FUNCDEF (-4) /* P4 is a pointer to a FuncDef structure */ -#define P4_KEYINFO (-5) /* P4 is a pointer to a KeyInfo structure */ -#define P4_EXPR (-6) /* P4 is a pointer to an Expr tree */ -#define P4_MEM (-7) /* P4 is a pointer to a Mem* structure */ -#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ -#define P4_VTAB (-8) /* P4 is a pointer to an sqlite3_vtab structure */ -#define P4_REAL (-9) /* P4 is a 64-bit floating point value */ -#define P4_INT64 (-10) /* P4 is a 64-bit signed integer */ -#define P4_INT32 (-11) /* P4 is a 32-bit signed integer */ -#define P4_INTARRAY (-12) /* P4 is a vector of 32-bit integers */ -#define P4_SUBPROGRAM (-13) /* P4 is a pointer to a SubProgram structure */ -#define P4_ADVANCE (-14) /* P4 is a pointer to BtreeNext() or BtreePrev() */ -#define P4_TABLE (-15) /* P4 is a pointer to a Table structure */ -#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ +#define P4_STATIC (-1) /* Pointer to a static string */ +#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */ +#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */ +#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */ +#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */ +/* Above do not own any resources. Must free those below */ +#define P4_FREE_IF_LE (-7) +#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */ +#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */ +#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */ +#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */ +#define P4_VTAB (-12) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_REAL (-13) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -12740,87 +13739,87 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Savepoint 0 #define OP_AutoCommit 1 #define OP_Transaction 2 -#define OP_SorterNext 3 -#define OP_PrevIfOpen 4 -#define OP_NextIfOpen 5 -#define OP_Prev 6 -#define OP_Next 7 +#define OP_SorterNext 3 /* jump */ +#define OP_PrevIfOpen 4 /* jump */ +#define OP_NextIfOpen 5 /* jump */ +#define OP_Prev 6 /* jump */ +#define OP_Next 7 /* jump */ #define OP_Checkpoint 8 #define OP_JournalMode 9 #define OP_Vacuum 10 -#define OP_VFilter 11 /* synopsis: iplan=r[P3] zplan='P4' */ +#define OP_VFilter 11 /* jump, synopsis: iplan=r[P3] zplan='P4' */ #define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */ -#define OP_Goto 13 -#define OP_Gosub 14 -#define OP_InitCoroutine 15 -#define OP_Yield 16 -#define OP_MustBeInt 17 -#define OP_Jump 18 +#define OP_Goto 13 /* jump */ +#define OP_Gosub 14 /* jump */ +#define OP_InitCoroutine 15 /* jump */ +#define OP_Yield 16 /* jump */ +#define OP_MustBeInt 17 /* jump */ +#define OP_Jump 18 /* jump */ #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_Once 20 -#define OP_If 21 -#define OP_IfNot 22 -#define OP_IfNullRow 23 /* synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ -#define OP_SeekLT 24 /* synopsis: key=r[P3@P4] */ -#define OP_SeekLE 25 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGE 26 /* synopsis: key=r[P3@P4] */ -#define OP_SeekGT 27 /* synopsis: key=r[P3@P4] */ -#define OP_NoConflict 28 /* synopsis: key=r[P3@P4] */ -#define OP_NotFound 29 /* synopsis: key=r[P3@P4] */ -#define OP_Found 30 /* synopsis: key=r[P3@P4] */ -#define OP_SeekRowid 31 /* synopsis: intkey=r[P3] */ -#define OP_NotExists 32 /* synopsis: intkey=r[P3] */ -#define OP_Last 33 -#define OP_IfSmaller 34 -#define OP_SorterSort 35 -#define OP_Sort 36 -#define OP_Rewind 37 -#define OP_IdxLE 38 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGT 39 /* synopsis: key=r[P3@P4] */ -#define OP_IdxLT 40 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGE 41 /* synopsis: key=r[P3@P4] */ -#define OP_RowSetRead 42 /* synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 43 /* synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 44 -#define OP_FkIfZero 45 /* synopsis: if fkctr[P1]==0 goto P2 */ -#define OP_IfPos 46 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ -#define OP_IfNotZero 47 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ -#define OP_DecrJumpZero 48 /* synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IncrVacuum 49 -#define OP_VNext 50 -#define OP_Init 51 /* synopsis: Start at P2 */ -#define OP_Return 52 -#define OP_EndCoroutine 53 -#define OP_HaltIfNull 54 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 55 -#define OP_Integer 56 /* synopsis: r[P2]=P1 */ -#define OP_Int64 57 /* synopsis: r[P2]=P4 */ -#define OP_String 58 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 59 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 60 /* synopsis: r[P1]=NULL */ -#define OP_Blob 61 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 62 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 63 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 64 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 65 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 66 /* synopsis: r[P2]=r[P1] */ -#define OP_ResultRow 67 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 68 -#define OP_Function0 69 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_Or 70 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ -#define OP_And 71 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ -#define OP_Function 72 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_AddImm 73 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_RealAffinity 74 -#define OP_IsNull 75 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */ -#define OP_NotNull 76 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ -#define OP_Ne 77 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */ -#define OP_Eq 78 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */ -#define OP_Gt 79 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */ -#define OP_Le 80 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */ -#define OP_Lt 81 /* same as TK_LT, synopsis: IF r[P3]<r[P1] */ -#define OP_Ge 82 /* same as TK_GE, synopsis: IF r[P3]>=r[P1] */ -#define OP_ElseNotEq 83 /* same as TK_ESCAPE */ +#define OP_Once 20 /* jump */ +#define OP_If 21 /* jump */ +#define OP_IfNot 22 /* jump */ +#define OP_IfNullRow 23 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ +#define OP_SeekLT 24 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekLE 25 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekGE 26 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekGT 27 /* jump, synopsis: key=r[P3@P4] */ +#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */ +#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */ +#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */ +#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */ +#define OP_Last 33 /* jump */ +#define OP_IfSmaller 34 /* jump */ +#define OP_SorterSort 35 /* jump */ +#define OP_Sort 36 /* jump */ +#define OP_Rewind 37 /* jump */ +#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */ +#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */ +#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */ +#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */ +#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */ +#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */ +#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */ +#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 46 /* jump */ +#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ +#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ +#define OP_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] */ +#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ +#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ +#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ +#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */ +#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */ +#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */ +#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */ +#define OP_IncrVacuum 60 /* jump */ +#define OP_VNext 61 /* jump */ +#define OP_Init 62 /* jump, synopsis: Start at P2 */ +#define OP_Return 63 +#define OP_EndCoroutine 64 +#define OP_HaltIfNull 65 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 66 +#define OP_Integer 67 /* synopsis: r[P2]=P1 */ +#define OP_Int64 68 /* synopsis: r[P2]=P4 */ +#define OP_String 69 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 70 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 71 /* synopsis: r[P1]=NULL */ +#define OP_Blob 72 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 73 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 74 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 75 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 76 /* synopsis: r[P2]=r[P1] */ +#define OP_IntCopy 77 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 78 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 79 +#define OP_AddImm 80 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_RealAffinity 81 +#define OP_Cast 82 /* synopsis: affinity(r[P1]) */ +#define OP_Permutation 83 #define OP_BitAnd 84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ #define OP_BitOr 85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ #define OP_ShiftLeft 86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */ @@ -12831,78 +13830,80 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Divide 91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ #define OP_Remainder 92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ #define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_Cast 94 /* synopsis: affinity(r[P1]) */ +#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */ #define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ -#define OP_Permutation 96 +#define OP_Column 96 /* synopsis: r[P3]=PX */ #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_Compare 98 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_Column 99 /* synopsis: r[P3]=PX */ -#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 102 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 103 -#define OP_SetCookie 104 -#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenDup 108 -#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 111 -#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 114 -#define OP_ColumnsUsed 115 -#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */ -#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_Delete 120 -#define OP_ResetCount 121 -#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 123 /* synopsis: r[P2]=data */ -#define OP_RowData 124 /* synopsis: r[P2]=data */ -#define OP_Rowid 125 /* synopsis: r[P2]=rowid */ -#define OP_NullRow 126 -#define OP_SorterInsert 127 /* synopsis: key=r[P2] */ -#define OP_IdxInsert 128 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 129 /* synopsis: key=r[P2@P3] */ -#define OP_Seek 130 /* synopsis: Move P3 to P1.rowid */ -#define OP_IdxRowid 131 /* synopsis: r[P2]=rowid */ +#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 100 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 101 +#define OP_SetCookie 102 +#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenDup 106 +#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 109 +#define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 112 +#define OP_ColumnsUsed 113 +#define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 115 /* synopsis: r[P2]=rowid */ +#define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 118 +#define OP_ResetCount 119 +#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 121 /* synopsis: r[P2]=data */ +#define OP_RowData 122 /* synopsis: r[P2]=data */ +#define OP_Rowid 123 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 124 +#define OP_SeekEnd 125 +#define OP_SorterInsert 126 /* synopsis: key=r[P2] */ +#define OP_IdxInsert 127 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 128 /* synopsis: key=r[P2@P3] */ +#define OP_DeferredSeek 129 /* synopsis: Move P3 to P1.rowid if needed */ +#define OP_IdxRowid 130 /* synopsis: r[P2]=rowid */ +#define OP_Destroy 131 #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_Destroy 133 -#define OP_Clear 134 -#define OP_ResetSorter 135 -#define OP_CreateIndex 136 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_CreateTable 137 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_SqlExec 138 -#define OP_ParseSchema 139 -#define OP_LoadAnalysis 140 -#define OP_DropTable 141 -#define OP_DropIndex 142 -#define OP_DropTrigger 143 -#define OP_IntegrityCk 144 -#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */ -#define OP_Param 146 -#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */ -#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 153 -#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 155 -#define OP_VCreate 156 -#define OP_VDestroy 157 -#define OP_VOpen 158 -#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 160 -#define OP_Pagecount 161 -#define OP_MaxPgcnt 162 -#define OP_CursorHint 163 -#define OP_Noop 164 -#define OP_Explain 165 +#define OP_Clear 133 +#define OP_ResetSorter 134 +#define OP_CreateBtree 135 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ +#define OP_SqlExec 136 +#define OP_ParseSchema 137 +#define OP_LoadAnalysis 138 +#define OP_DropTable 139 +#define OP_DropIndex 140 +#define OP_DropTrigger 141 +#define OP_IntegrityCk 142 +#define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 144 +#define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 151 +#define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 153 +#define OP_VCreate 154 +#define OP_VDestroy 155 +#define OP_VOpen 156 +#define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 158 +#define OP_Pagecount 159 +#define OP_MaxPgcnt 160 +#define OP_PureFunc0 161 +#define OP_Function0 162 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_PureFunc 163 +#define OP_Function 164 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_CursorHint 165 +#define OP_Noop 166 +#define OP_Explain 167 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -12920,22 +13921,23 @@ typedef struct VdbeOpList VdbeOpList; /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\ /* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\ /* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ -/* 40 */ 0x01, 0x01, 0x23, 0x0b, 0x01, 0x01, 0x03, 0x03,\ -/* 48 */ 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x00,\ -/* 56 */ 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00,\ -/* 64 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x26, 0x26,\ -/* 72 */ 0x00, 0x02, 0x02, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\ -/* 80 */ 0x0b, 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26,\ -/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x02, 0x12,\ -/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ +/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\ +/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ +/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x02,\ +/* 64 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\ +/* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\ +/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ +/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ -/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04,\ -/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\ -/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,} +/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04,\ +/* 128 */ 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10,\ +/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ +/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\ +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ +/* 160 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +} /* The sqlite3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -12943,12 +13945,18 @@ typedef struct VdbeOpList VdbeOpList; ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ -#define SQLITE_MX_JUMP_OPCODE 83 /* Maximum JUMP opcode */ +#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */ /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ /* +** Additional non-public SQLITE_PREPARE_* flags +*/ +#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ +#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */ + +/* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ @@ -13005,7 +14013,8 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); +SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8); SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8); @@ -13027,6 +14036,8 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); #endif +SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*); + /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on ** each VDBE opcode. ** @@ -13252,6 +14263,7 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*); /* Operations on page references. */ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); @@ -13371,6 +14383,7 @@ struct PgHdr { sqlite3_pcache_page *pPage; /* Pcache object page handle */ void *pData; /* Page data */ void *pExtra; /* Extra content */ + PCache *pCache; /* PRIVATE: Cache that owns this page */ PgHdr *pDirty; /* Transient list of dirty sorted by pgno */ Pager *pPager; /* The pager this page is part of */ Pgno pgno; /* Page number for this page */ @@ -13380,14 +14393,15 @@ struct PgHdr { u16 flags; /* PGHDR flags defined below */ /********************************************************************** - ** Elements above are public. All that follows is private to pcache.c - ** and should not be accessed by other modules. + ** Elements above, except pCache, are public. All that follow are + ** private to pcache.c and should not be accessed by other modules. + ** pCache is grouped with the public elements for efficiency. */ i16 nRef; /* Number of users of this page */ - PCache *pCache; /* Cache that owns this page */ - PgHdr *pDirtyNext; /* Next element in list of dirty pages */ PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ + /* NB: pDirtyNext and pDirtyPrev are undefined if the + ** PgHdr object is not dirty */ }; /* Bit values for PgHdr.flags */ @@ -13769,10 +14783,12 @@ 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 *); @@ -13981,6 +14997,7 @@ struct Schema { #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ #define DB_UnresetViews 0x0002 /* Some views have defined column names */ #define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ +#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */ /* ** The number of different kinds of things that can be limited @@ -14012,9 +15029,9 @@ struct Lookaside { u32 bDisable; /* Only operate the lookaside when zero */ u16 sz; /* Size of each buffer in bytes */ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ - int nOut; /* Number of buffers currently checked out */ - int mxOut; /* Highwater mark for nOut */ - int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ + u32 nSlot; /* Number of lookaside slots allocated */ + u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ + LookasideSlot *pInit; /* List of buffers not previously used */ LookasideSlot *pFree; /* List of available buffers */ void *pStart; /* First byte of available memory space */ void *pEnd; /* First byte past end of available space */ @@ -14093,9 +15110,11 @@ struct sqlite3 { sqlite3_mutex *mutex; /* Connection mutex */ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ - int flags; /* Miscellaneous flags. See below */ + u32 mDbFlags; /* flags recording internal state */ + u32 flags; /* flags settable by pragmas. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ i64 szMmap; /* Default mmap_size setting */ + u32 nSchemaLock; /* Do not reset the schema when non-zero */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ @@ -14227,8 +15246,8 @@ struct sqlite3 { ** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC ** SQLITE_CacheSpill == PAGER_CACHE_SPILL */ -#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ -#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */ +#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */ +#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */ #define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */ #define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */ #define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */ @@ -14239,30 +15258,36 @@ struct sqlite3 { /* the count using a callback. */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ -#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ -#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ -#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ -#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */ -#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ -#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */ -#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */ -#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */ -#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */ -#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */ -#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */ -#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */ -#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */ -#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */ -#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */ -#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ -#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ -#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ -#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ -#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ +#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */ +#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */ +#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */ +#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */ +#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */ +#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */ +#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */ +#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */ +#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */ +#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */ +#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */ +#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */ +#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee */ +/* Flags used only if debugging */ +#ifdef SQLITE_DEBUG +#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */ +#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */ +#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */ +#endif +/* +** Allowed values for sqlite3.mDbFlags +*/ +#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ +#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ +#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the @@ -14273,15 +15298,15 @@ struct sqlite3 { #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ -/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */ -#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ -#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ -#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ -#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ -#define SQLITE_Transitive 0x0200 /* Transitive constraints */ -#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ +#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ +#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */ +#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */ +#define SQLITE_Transitive 0x0080 /* Transitive constraints */ +#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */ +#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */ +#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */ #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ -#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */ + /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* @@ -14399,7 +15424,14 @@ struct FuncDestructor { ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and ** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions ** and functions like sqlite_version() that can change, but not during -** a single query. +** a single query. The iArg is ignored. The user-data is always set +** to a NULL pointer. The bNC parameter is not used. +** +** PURE_DATE(zName, nArg, iArg, bNC, xFunc) +** Used for "pure" date/time functions, this macro is like DFUNCTION +** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is +** ignored and the user-data for these functions is set to an +** arbitrary non-NULL pointer. The bNC parameter is not used. ** ** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) ** Used to create an aggregate function definition implemented by @@ -14422,8 +15454,11 @@ struct FuncDestructor { {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ - SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \ + 0, 0, xFunc, 0, #zName, {0} } +#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ + (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} } #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} } @@ -14802,8 +15837,8 @@ struct FKey { struct KeyInfo { u32 nRef; /* Number of references to this KeyInfo object */ u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ - u16 nField; /* Number of key columns in the index */ - u16 nXField; /* Number of columns beyond the key columns */ + u16 nKeyField; /* Number of key columns in the index */ + u16 nAllField; /* Total columns, including key plus others */ sqlite3 *db; /* The database connection */ u8 *aSortOrder; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ @@ -14850,8 +15885,8 @@ struct UnpackedRecord { u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ - i8 r1; /* Value to return if (lhs > rhs) */ - i8 r2; /* Value to return if (rhs < lhs) */ + i8 r1; /* Value to return if (lhs < rhs) */ + i8 r2; /* Value to return if (lhs > rhs) */ u8 eqSeen; /* True if an equality comparison has been seen */ }; @@ -15135,7 +16170,8 @@ struct Expr { ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. */ + Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL + ** for a column of an index on an expression */ }; /* @@ -15143,8 +16179,8 @@ struct Expr { */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ #define EP_Agg 0x000002 /* Contains one or more aggregate functions */ -#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */ -#define EP_Error 0x000008 /* Expression contains one or more errors */ + /* 0x000004 // available for use */ + /* 0x000008 // available for use */ #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ @@ -15223,7 +16259,6 @@ struct Expr { */ struct ExprList { int nExpr; /* Number of expressions on the list */ - int nAlloc; /* Number of a[] slots allocated */ struct ExprList_item { /* For each expression in the list */ Expr *pExpr; /* The parse tree for this expression */ char *zName; /* Token associated with this expression */ @@ -15611,10 +16646,10 @@ struct Select { */ struct SelectDest { u8 eDest; /* How to dispose of the results. On of SRT_* above. */ - char *zAffSdst; /* Affinity used when eDest==SRT_Set */ int iSDParm; /* A parameter used by the eDest disposal method */ int iSdst; /* Base register where results are written */ int nSdst; /* Number of registers allocated */ + char *zAffSdst; /* Affinity used when eDest==SRT_Set */ ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ }; @@ -15724,8 +16759,8 @@ struct Parse { int nMem; /* Number of memory cells used so far */ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ - int ckBase; /* Base register of data during check constraints */ - int iSelfTab; /* Table of an index whose exprs are being coded */ + int iSelfTab; /* Table for associated with an index on expr, or negative + ** of the base register during check-constraint eval */ int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ int nLabel; /* Number of labels used */ @@ -15748,7 +16783,7 @@ struct Parse { AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ - int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */ + int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */ 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 */ @@ -15977,11 +17012,10 @@ struct DbFixer { */ struct StrAccum { sqlite3 *db; /* Optional database for lookaside. Can be NULL */ - char *zBase; /* A base allocation. Not from malloc. */ char *zText; /* The string collected so far */ - u32 nChar; /* Length of the string so far */ u32 nAlloc; /* Amount of space allocated in zText */ u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ + u32 nChar; /* Length of the string so far */ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ u8 printfFlags; /* SQLITE_PRINTF flags below */ }; @@ -16016,6 +17050,7 @@ struct Sqlite3Config { int bFullMutex; /* True to enable full mutexing */ int bOpenUri; /* True to interpret filenames as URIs */ int bUseCis; /* Use covering indices for full-scans */ + int bSmallMalloc; /* Avoid large memory allocations if true */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ @@ -16029,9 +17064,6 @@ struct Sqlite3Config { int mnReq, mxReq; /* Min and max heap requests sizes */ sqlite3_int64 szMmap; /* mmap() space per open file */ sqlite3_int64 mxMmap; /* Maximum value for szMmap */ - void *pScratch; /* Scratch memory */ - int szScratch; /* Size of each scratch buffer */ - int nScratch; /* Number of scratch buffers */ void *pPage; /* Page cache memory */ int szPage; /* Size of each page in pPage[] */ int nPage; /* Number of pages in pPage[] */ @@ -16117,6 +17149,11 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); +SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); +SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); +#endif /* ** Return code from the parse-tree walking primitives and their @@ -16178,11 +17215,14 @@ SQLITE_PRIVATE int sqlite3CantopenError(int); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3NomemError(int); SQLITE_PRIVATE int sqlite3IoerrnomemError(int); +SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno); # define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__) # define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__) +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) #else # define SQLITE_NOMEM_BKPT SQLITE_NOMEM # define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__) #endif /* @@ -16263,8 +17303,6 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*); SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*); SQLITE_PRIVATE int sqlite3MallocSize(void*); SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*); -SQLITE_PRIVATE void *sqlite3ScratchMalloc(int); -SQLITE_PRIVATE void sqlite3ScratchFree(void*); SQLITE_PRIVATE void *sqlite3PageMalloc(int); SQLITE_PRIVATE void sqlite3PageFree(void*); SQLITE_PRIVATE void sqlite3MemSetDefault(void); @@ -16320,6 +17358,7 @@ SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int); SQLITE_PRIVATE void sqlite3StatusUp(int, int); SQLITE_PRIVATE void sqlite3StatusDown(int, int); SQLITE_PRIVATE void sqlite3StatusHighwater(int, int); +SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*); /* Access to mutexes used by sqlite3_status() */ SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); @@ -16551,10 +17590,10 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); -SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); -SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); @@ -16568,8 +17607,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); -SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*); -SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*); +SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int); SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); @@ -16690,7 +17728,9 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); SQLITE_PRIVATE int sqlite3Atoi(const char*); +#ifndef SQLITE_OMIT_UTF16 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 LogEst sqlite3LogEst(u64); @@ -16755,6 +17795,8 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); +SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr); +SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*); SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); @@ -16779,7 +17821,9 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*); SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*); SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *); +#ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8); +#endif SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION @@ -17036,7 +18080,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*); SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *); -#ifdef SQLITE_ENABLE_ATOMIC_WRITE +#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ + || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *); #endif @@ -17122,8 +18167,7 @@ SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8); #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ -#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */ -#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */ +#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */ /* ** Threading interface @@ -17133,6 +18177,9 @@ SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*); SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**); #endif +#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST) +SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3*); +#endif #if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST) SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*); #endif @@ -17143,6 +18190,10 @@ SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int); SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int); SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*); +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt); +#endif + #endif /* SQLITEINT_H */ /************** End of sqliteInt.h *******************************************/ @@ -17348,6 +18399,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ + 0, /* bSmallMalloc */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ @@ -17360,9 +18412,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, 0, /* mnHeap, mxHeap */ SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ SQLITE_MAX_MMAP_SIZE, /* mxMmap */ - (void*)0, /* pScratch */ - 0, /* szScratch */ - 0, /* nScratch */ (void*)0, /* pPage */ 0, /* szPage */ SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */ @@ -17447,472 +18496,6 @@ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER; SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY"; /************** End of global.c **********************************************/ -/************** Begin file ctime.c *******************************************/ -/* -** 2010 February 23 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** -** This file implements routines used to report what compile-time options -** SQLite was built with. -*/ - -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS - -/* #include "sqliteInt.h" */ - -/* -** An array of names of all compile-time options. This array should -** be sorted A-Z. -** -** This array looks large, but in a typical installation actually uses -** only a handful of compile-time options, so most times this array is usually -** rather short and uses little memory space. -*/ -static const char * const azCompileOpt[] = { - -/* These macros are provided to "stringify" the value of the define -** for those options in which the value is meaningful. */ -#define CTIMEOPT_VAL_(opt) #opt -#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt) - -#if SQLITE_32BIT_ROWID - "32BIT_ROWID", -#endif -#if SQLITE_4_BYTE_ALIGNED_MALLOC - "4_BYTE_ALIGNED_MALLOC", -#endif -#if SQLITE_CASE_SENSITIVE_LIKE - "CASE_SENSITIVE_LIKE", -#endif -#if SQLITE_CHECK_PAGES - "CHECK_PAGES", -#endif -#if defined(__clang__) && defined(__clang_major__) - "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "." - CTIMEOPT_VAL(__clang_minor__) "." - CTIMEOPT_VAL(__clang_patchlevel__), -#elif defined(_MSC_VER) - "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER), -#elif defined(__GNUC__) && defined(__VERSION__) - "COMPILER=gcc-" __VERSION__, -#endif -#if SQLITE_COVERAGE_TEST - "COVERAGE_TEST", -#endif -#ifdef SQLITE_DEBUG - "DEBUG", -#endif -#if SQLITE_DEFAULT_LOCKING_MODE - "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), -#endif -#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) - "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), -#endif -#if SQLITE_DEFAULT_SYNCHRONOUS - "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS), -#endif -#if SQLITE_DEFAULT_WAL_SYNCHRONOUS - "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS), -#endif -#if SQLITE_DIRECT_OVERFLOW_READ - "DIRECT_OVERFLOW_READ", -#endif -#if SQLITE_DISABLE_DIRSYNC - "DISABLE_DIRSYNC", -#endif -#if SQLITE_DISABLE_LFS - "DISABLE_LFS", -#endif -#if SQLITE_ENABLE_8_3_NAMES - "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES), -#endif -#if SQLITE_ENABLE_API_ARMOR - "ENABLE_API_ARMOR", -#endif -#if SQLITE_ENABLE_ATOMIC_WRITE - "ENABLE_ATOMIC_WRITE", -#endif -#if SQLITE_ENABLE_CEROD - "ENABLE_CEROD", -#endif -#if SQLITE_ENABLE_COLUMN_METADATA - "ENABLE_COLUMN_METADATA", -#endif -#if SQLITE_ENABLE_DBSTAT_VTAB - "ENABLE_DBSTAT_VTAB", -#endif -#if SQLITE_ENABLE_EXPENSIVE_ASSERT - "ENABLE_EXPENSIVE_ASSERT", -#endif -#if SQLITE_ENABLE_FTS1 - "ENABLE_FTS1", -#endif -#if SQLITE_ENABLE_FTS2 - "ENABLE_FTS2", -#endif -#if SQLITE_ENABLE_FTS3 - "ENABLE_FTS3", -#endif -#if SQLITE_ENABLE_FTS3_PARENTHESIS - "ENABLE_FTS3_PARENTHESIS", -#endif -#if SQLITE_ENABLE_FTS4 - "ENABLE_FTS4", -#endif -#if SQLITE_ENABLE_FTS5 - "ENABLE_FTS5", -#endif -#if SQLITE_ENABLE_ICU - "ENABLE_ICU", -#endif -#if SQLITE_ENABLE_IOTRACE - "ENABLE_IOTRACE", -#endif -#if SQLITE_ENABLE_JSON1 - "ENABLE_JSON1", -#endif -#if SQLITE_ENABLE_LOAD_EXTENSION - "ENABLE_LOAD_EXTENSION", -#endif -#if SQLITE_ENABLE_LOCKING_STYLE - "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE), -#endif -#if SQLITE_ENABLE_MEMORY_MANAGEMENT - "ENABLE_MEMORY_MANAGEMENT", -#endif -#if SQLITE_ENABLE_MEMSYS3 - "ENABLE_MEMSYS3", -#endif -#if SQLITE_ENABLE_MEMSYS5 - "ENABLE_MEMSYS5", -#endif -#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK - "ENABLE_OVERSIZE_CELL_CHECK", -#endif -#if SQLITE_ENABLE_RTREE - "ENABLE_RTREE", -#endif -#if defined(SQLITE_ENABLE_STAT4) - "ENABLE_STAT4", -#elif defined(SQLITE_ENABLE_STAT3) - "ENABLE_STAT3", -#endif -#if SQLITE_ENABLE_UNLOCK_NOTIFY - "ENABLE_UNLOCK_NOTIFY", -#endif -#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT - "ENABLE_UPDATE_DELETE_LIMIT", -#endif -#if defined(SQLITE_ENABLE_URI_00_ERROR) - "ENABLE_URI_00_ERROR", -#endif -#if SQLITE_HAS_CODEC - "HAS_CODEC", -#endif -#if HAVE_ISNAN || SQLITE_HAVE_ISNAN - "HAVE_ISNAN", -#endif -#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX - "HOMEGROWN_RECURSIVE_MUTEX", -#endif -#if SQLITE_IGNORE_AFP_LOCK_ERRORS - "IGNORE_AFP_LOCK_ERRORS", -#endif -#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS - "IGNORE_FLOCK_LOCK_ERRORS", -#endif -#ifdef SQLITE_INT64_TYPE - "INT64_TYPE", -#endif -#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS - "LIKE_DOESNT_MATCH_BLOBS", -#endif -#if SQLITE_LOCK_TRACE - "LOCK_TRACE", -#endif -#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc) - "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), -#endif -#ifdef SQLITE_MAX_SCHEMA_RETRY - "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), -#endif -#if SQLITE_MEMDEBUG - "MEMDEBUG", -#endif -#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT - "MIXED_ENDIAN_64BIT_FLOAT", -#endif -#if SQLITE_NO_SYNC - "NO_SYNC", -#endif -#if SQLITE_OMIT_ALTERTABLE - "OMIT_ALTERTABLE", -#endif -#if SQLITE_OMIT_ANALYZE - "OMIT_ANALYZE", -#endif -#if SQLITE_OMIT_ATTACH - "OMIT_ATTACH", -#endif -#if SQLITE_OMIT_AUTHORIZATION - "OMIT_AUTHORIZATION", -#endif -#if SQLITE_OMIT_AUTOINCREMENT - "OMIT_AUTOINCREMENT", -#endif -#if SQLITE_OMIT_AUTOINIT - "OMIT_AUTOINIT", -#endif -#if SQLITE_OMIT_AUTOMATIC_INDEX - "OMIT_AUTOMATIC_INDEX", -#endif -#if SQLITE_OMIT_AUTORESET - "OMIT_AUTORESET", -#endif -#if SQLITE_OMIT_AUTOVACUUM - "OMIT_AUTOVACUUM", -#endif -#if SQLITE_OMIT_BETWEEN_OPTIMIZATION - "OMIT_BETWEEN_OPTIMIZATION", -#endif -#if SQLITE_OMIT_BLOB_LITERAL - "OMIT_BLOB_LITERAL", -#endif -#if SQLITE_OMIT_BTREECOUNT - "OMIT_BTREECOUNT", -#endif -#if SQLITE_OMIT_CAST - "OMIT_CAST", -#endif -#if SQLITE_OMIT_CHECK - "OMIT_CHECK", -#endif -#if SQLITE_OMIT_COMPLETE - "OMIT_COMPLETE", -#endif -#if SQLITE_OMIT_COMPOUND_SELECT - "OMIT_COMPOUND_SELECT", -#endif -#if SQLITE_OMIT_CTE - "OMIT_CTE", -#endif -#if SQLITE_OMIT_DATETIME_FUNCS - "OMIT_DATETIME_FUNCS", -#endif -#if SQLITE_OMIT_DECLTYPE - "OMIT_DECLTYPE", -#endif -#if SQLITE_OMIT_DEPRECATED - "OMIT_DEPRECATED", -#endif -#if SQLITE_OMIT_DISKIO - "OMIT_DISKIO", -#endif -#if SQLITE_OMIT_EXPLAIN - "OMIT_EXPLAIN", -#endif -#if SQLITE_OMIT_FLAG_PRAGMAS - "OMIT_FLAG_PRAGMAS", -#endif -#if SQLITE_OMIT_FLOATING_POINT - "OMIT_FLOATING_POINT", -#endif -#if SQLITE_OMIT_FOREIGN_KEY - "OMIT_FOREIGN_KEY", -#endif -#if SQLITE_OMIT_GET_TABLE - "OMIT_GET_TABLE", -#endif -#if SQLITE_OMIT_INCRBLOB - "OMIT_INCRBLOB", -#endif -#if SQLITE_OMIT_INTEGRITY_CHECK - "OMIT_INTEGRITY_CHECK", -#endif -#if SQLITE_OMIT_LIKE_OPTIMIZATION - "OMIT_LIKE_OPTIMIZATION", -#endif -#if SQLITE_OMIT_LOAD_EXTENSION - "OMIT_LOAD_EXTENSION", -#endif -#if SQLITE_OMIT_LOCALTIME - "OMIT_LOCALTIME", -#endif -#if SQLITE_OMIT_LOOKASIDE - "OMIT_LOOKASIDE", -#endif -#if SQLITE_OMIT_MEMORYDB - "OMIT_MEMORYDB", -#endif -#if SQLITE_OMIT_OR_OPTIMIZATION - "OMIT_OR_OPTIMIZATION", -#endif -#if SQLITE_OMIT_PAGER_PRAGMAS - "OMIT_PAGER_PRAGMAS", -#endif -#if SQLITE_OMIT_PRAGMA - "OMIT_PRAGMA", -#endif -#if SQLITE_OMIT_PROGRESS_CALLBACK - "OMIT_PROGRESS_CALLBACK", -#endif -#if SQLITE_OMIT_QUICKBALANCE - "OMIT_QUICKBALANCE", -#endif -#if SQLITE_OMIT_REINDEX - "OMIT_REINDEX", -#endif -#if SQLITE_OMIT_SCHEMA_PRAGMAS - "OMIT_SCHEMA_PRAGMAS", -#endif -#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS - "OMIT_SCHEMA_VERSION_PRAGMAS", -#endif -#if SQLITE_OMIT_SHARED_CACHE - "OMIT_SHARED_CACHE", -#endif -#if SQLITE_OMIT_SUBQUERY - "OMIT_SUBQUERY", -#endif -#if SQLITE_OMIT_TCL_VARIABLE - "OMIT_TCL_VARIABLE", -#endif -#if SQLITE_OMIT_TEMPDB - "OMIT_TEMPDB", -#endif -#if SQLITE_OMIT_TRACE - "OMIT_TRACE", -#endif -#if SQLITE_OMIT_TRIGGER - "OMIT_TRIGGER", -#endif -#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION - "OMIT_TRUNCATE_OPTIMIZATION", -#endif -#if SQLITE_OMIT_UTF16 - "OMIT_UTF16", -#endif -#if SQLITE_OMIT_VACUUM - "OMIT_VACUUM", -#endif -#if SQLITE_OMIT_VIEW - "OMIT_VIEW", -#endif -#if SQLITE_OMIT_VIRTUALTABLE - "OMIT_VIRTUALTABLE", -#endif -#if SQLITE_OMIT_WAL - "OMIT_WAL", -#endif -#if SQLITE_OMIT_WSD - "OMIT_WSD", -#endif -#if SQLITE_OMIT_XFER_OPT - "OMIT_XFER_OPT", -#endif -#if SQLITE_PERFORMANCE_TRACE - "PERFORMANCE_TRACE", -#endif -#if SQLITE_PROXY_DEBUG - "PROXY_DEBUG", -#endif -#if SQLITE_RTREE_INT_ONLY - "RTREE_INT_ONLY", -#endif -#if SQLITE_SECURE_DELETE - "SECURE_DELETE", -#endif -#if SQLITE_SMALL_STACK - "SMALL_STACK", -#endif -#if SQLITE_SOUNDEX - "SOUNDEX", -#endif -#if SQLITE_SYSTEM_MALLOC - "SYSTEM_MALLOC", -#endif -#if SQLITE_TCL - "TCL", -#endif -#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc) - "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), -#endif -#if SQLITE_TEST - "TEST", -#endif -#if defined(SQLITE_THREADSAFE) - "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), -#endif -#if SQLITE_UNTESTABLE - "UNTESTABLE" -#endif -#if SQLITE_USE_ALLOCA - "USE_ALLOCA", -#endif -#if SQLITE_USER_AUTHENTICATION - "USER_AUTHENTICATION", -#endif -#if SQLITE_WIN32_MALLOC - "WIN32_MALLOC", -#endif -#if SQLITE_ZERO_MALLOC - "ZERO_MALLOC" -#endif -}; - -/* -** Given the name of a compile-time option, return true if that option -** was used and false if not. -** -** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix -** is not required for a match. -*/ -SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ - int i, n; - -#if SQLITE_ENABLE_API_ARMOR - if( zOptName==0 ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif - if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; - n = sqlite3Strlen30(zOptName); - - /* Since ArraySize(azCompileOpt) is normally in single digits, a - ** linear search is adequate. No need for a binary search. */ - for(i=0; i<ArraySize(azCompileOpt); i++){ - if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0 - && sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0 - ){ - return 1; - } - } - return 0; -} - -/* -** Return the N-th compile-time option string. If N is out of range, -** return a NULL pointer. -*/ -SQLITE_API const char *sqlite3_compileoption_get(int N){ - if( N>=0 && N<ArraySize(azCompileOpt) ){ - return azCompileOpt[N]; - } - return 0; -} - -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - -/************** End of ctime.c ***********************************************/ /************** Begin file status.c ******************************************/ /* ** 2008 June 18 @@ -18030,18 +18613,18 @@ struct VdbeCursor { u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0 ** if there have been no prior seeks on the cursor. */ - /* NB: seekResult does not distinguish between "no seeks have ever occurred - ** on this cursor" and "the most recent seek was an exact match". */ + /* seekResult does not distinguish between "no seeks have ever occurred + ** on this cursor" and "the most recent seek was an exact match". + ** For CURTYPE_PSEUDO, seekResult is the register holding the record */ /* When a new VdbeCursor is allocated, only the fields above are zeroed. ** The fields that follow are uninitialized, and must be individually ** initialized prior to first use. */ VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ union { - BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ - sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ - int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ - VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ + BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */ + sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ + VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ } uc; KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ u32 iHdrOffset; /* Offset to next unparsed byte of the header */ @@ -18123,7 +18706,8 @@ struct sqlite3_value { union MemValue { double r; /* Real value used when MEM_Real is set in flags */ i64 i; /* Integer value used when MEM_Int is set in flags */ - int nZero; /* Used when bit MEM_Zero is set in flags */ + int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ + const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ @@ -18155,7 +18739,8 @@ struct sqlite3_value { ** representations of the value stored in the Mem struct. ** ** If the MEM_Null flag is set, then the value is an SQL NULL value. -** No other flags may be set in this case. +** For a pointer type created using sqlite3_bind_pointer() or +** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set. ** ** If the MEM_Str flag is set then Mem.z points at a string representation. ** Usually this is encoded in the same unicode encoding as the main @@ -18163,7 +18748,7 @@ struct sqlite3_value { ** set, then the string is nul terminated. The MEM_Int and MEM_Real ** flags may coexist with the MEM_Str flag. */ -#define MEM_Null 0x0001 /* Value is NULL */ +#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ @@ -18173,7 +18758,7 @@ struct sqlite3_value { #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ #define MEM_Undefined 0x0080 /* Value is undefined */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ -#define MEM_TypeMask 0x81ff /* Mask of type bits */ +#define MEM_TypeMask 0xc1ff /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of @@ -18181,7 +18766,7 @@ struct sqlite3_value { ** policy for Mem.z. The MEM_Term flag tells us whether or not the ** string is \000 or \u0000 terminated */ -#define MEM_Term 0x0200 /* String rep is nul terminated */ +#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */ #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ #define MEM_Static 0x0800 /* Mem.z points to a static string */ #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ @@ -18316,6 +18901,7 @@ struct Vdbe { u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ + u8 prepFlags; /* SQLITE_PREPARE_* flags */ bft expired:1; /* True if the VM needs to be recompiled */ bft doingRerun:1; /* True if rerunning after an auto-reprepare */ bft explain:2; /* True if EXPLAIN present on SQL command */ @@ -18324,10 +18910,9 @@ struct Vdbe { 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 isPrepareV2:1; /* True if prepared with prepare_v2() */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */ + u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ @@ -18409,6 +18994,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif +SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); @@ -18440,7 +19026,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *); SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *); SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *); SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *); -SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *); +SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *); SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); @@ -18468,12 +19054,14 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int); # define sqlite3VdbeCheckFk(p,i) 0 #endif -SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); #endif -SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem); +#ifndef SQLITE_OMIT_UTF16 +SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8); +SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem); +#endif #ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *); @@ -18594,7 +19182,6 @@ SQLITE_PRIVATE void sqlite3StatusHighwater(int op, int X){ : sqlite3MallocMutex()) ); assert( op==SQLITE_STATUS_MALLOC_SIZE || op==SQLITE_STATUS_PAGECACHE_SIZE - || op==SQLITE_STATUS_SCRATCH_SIZE || op==SQLITE_STATUS_PARSER_STACK ); if( newValue>wsdStat.mxValue[op] ){ wsdStat.mxValue[op] = newValue; @@ -18644,6 +19231,28 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF } /* +** Return the number of LookasideSlot elements on the linked list +*/ +static u32 countLookasideSlots(LookasideSlot *p){ + u32 cnt = 0; + while( p ){ + p = p->pNext; + cnt++; + } + return cnt; +} + +/* +** Count the number of slots of lookaside memory that are outstanding +*/ +SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){ + u32 nInit = countLookasideSlots(db->lookaside.pInit); + u32 nFree = countLookasideSlots(db->lookaside.pFree); + if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit; + return db->lookaside.nSlot - (nInit+nFree); +} + +/* ** Query status information for a single database connection */ SQLITE_API int sqlite3_db_status( @@ -18662,10 +19271,15 @@ SQLITE_API int sqlite3_db_status( sqlite3_mutex_enter(db->mutex); switch( op ){ case SQLITE_DBSTATUS_LOOKASIDE_USED: { - *pCurrent = db->lookaside.nOut; - *pHighwater = db->lookaside.mxOut; + *pCurrent = sqlite3LookasideUsed(db, pHighwater); if( resetFlag ){ - db->lookaside.mxOut = db->lookaside.nOut; + LookasideSlot *p = db->lookaside.pFree; + if( p ){ + while( p->pNext ) p = p->pNext; + p->pNext = db->lookaside.pInit; + db->lookaside.pInit = db->lookaside.pFree; + db->lookaside.pFree = 0; + } } break; } @@ -19212,7 +19826,7 @@ static int parseDateOrTime( return 0; }else if( parseHhMmSs(zDate, p)==0 ){ return 0; - }else if( sqlite3StrICmp(zDate,"now")==0){ + }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ return setDateTimeToCurrent(context, p); }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ setRawDateNumber(p, r); @@ -19495,7 +20109,7 @@ static int parseModifier( ** Assuming the current time value is UTC (a.k.a. GMT), shift it to ** show local time. */ - if( sqlite3_stricmp(z, "localtime")==0 ){ + if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ computeJD(p); p->iJD += localtimeOffset(p, pCtx, &rc); clearYMD_HMS_TZ(p); @@ -19521,7 +20135,7 @@ static int parseModifier( } } #ifndef SQLITE_OMIT_LOCALTIME - else if( sqlite3_stricmp(z, "utc")==0 ){ + else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ if( p->tzSet==0 ){ sqlite3_int64 c1; computeJD(p); @@ -20057,11 +20671,11 @@ static void currentTimeFunc( SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ static FuncDef aDateTimeFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS - DFUNCTION(julianday, -1, 0, 0, juliandayFunc ), - DFUNCTION(date, -1, 0, 0, dateFunc ), - DFUNCTION(time, -1, 0, 0, timeFunc ), - DFUNCTION(datetime, -1, 0, 0, datetimeFunc ), - DFUNCTION(strftime, -1, 0, 0, strftimeFunc ), + PURE_DATE(julianday, -1, 0, 0, juliandayFunc ), + PURE_DATE(date, -1, 0, 0, dateFunc ), + PURE_DATE(time, -1, 0, 0, timeFunc ), + PURE_DATE(datetime, -1, 0, 0, datetimeFunc ), + PURE_DATE(strftime, -1, 0, 0, strftimeFunc ), DFUNCTION(current_time, 0, 0, 0, ctimeFunc ), DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), DFUNCTION(current_date, 0, 0, 0, cdateFunc ), @@ -20176,7 +20790,7 @@ SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){ } SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){ DO_OS_MALLOC_TEST(id); - return id->pMethods->xSync(id, flags); + return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK; } SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ DO_OS_MALLOC_TEST(id); @@ -20231,6 +20845,7 @@ SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ return id->pMethods->xDeviceCharacteristics(id); } +#ifndef SQLITE_OMIT_WAL SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){ return id->pMethods->xShmLock(id, offset, n, flags); } @@ -20250,6 +20865,7 @@ SQLITE_PRIVATE int sqlite3OsShmMap( DO_OS_MALLOC_TEST(id); return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); } +#endif /* SQLITE_OMIT_WAL */ #if SQLITE_MAX_MMAP_SIZE>0 /* The real implementation of xFetch and xUnfetch */ @@ -24247,14 +24863,6 @@ SQLITE_API int sqlite3_release_memory(int n){ } /* -** An instance of the following object records the location of -** each unused scratch buffer. -*/ -typedef struct ScratchFreeslot { - struct ScratchFreeslot *pNext; /* Next unused scratch buffer */ -} ScratchFreeslot; - -/* ** State information local to the memory allocation subsystem. */ static SQLITE_WSD struct Mem0Global { @@ -24262,21 +24870,11 @@ static SQLITE_WSD struct Mem0Global { sqlite3_int64 alarmThreshold; /* The soft heap limit */ /* - ** Pointers to the end of sqlite3GlobalConfig.pScratch memory - ** (so that a range test can be used to determine if an allocation - ** being freed came from pScratch) and a pointer to the list of - ** unused scratch allocations. - */ - void *pScratchEnd; - ScratchFreeslot *pScratchFree; - u32 nScratchFree; - - /* ** True if heap is nearly "full" where "full" is defined by the ** sqlite3_soft_heap_limit() setting. */ int nearlyFull; -} mem0 = { 0, 0, 0, 0, 0, 0 }; +} mem0 = { 0, 0, 0 }; #define mem0 GLOBAL(struct Mem0Global, mem0) @@ -24346,28 +24944,6 @@ SQLITE_PRIVATE int sqlite3MallocInit(void){ } memset(&mem0, 0, sizeof(mem0)); mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); - if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100 - && sqlite3GlobalConfig.nScratch>0 ){ - int i, n, sz; - ScratchFreeslot *pSlot; - sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch); - sqlite3GlobalConfig.szScratch = sz; - pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch; - n = sqlite3GlobalConfig.nScratch; - mem0.pScratchFree = pSlot; - mem0.nScratchFree = n; - for(i=0; i<n-1; i++){ - pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot); - pSlot = pSlot->pNext; - } - pSlot->pNext = 0; - mem0.pScratchEnd = (void*)&pSlot[1]; - }else{ - mem0.pScratchEnd = 0; - sqlite3GlobalConfig.pScratch = 0; - sqlite3GlobalConfig.szScratch = 0; - sqlite3GlobalConfig.nScratch = 0; - } if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512 || sqlite3GlobalConfig.nPage<=0 ){ sqlite3GlobalConfig.pPage = 0; @@ -24519,105 +25095,6 @@ SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){ } /* -** Each thread may only have a single outstanding allocation from -** xScratchMalloc(). We verify this constraint in the single-threaded -** case by setting scratchAllocOut to 1 when an allocation -** is outstanding clearing it when the allocation is freed. -*/ -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) -static int scratchAllocOut = 0; -#endif - - -/* -** Allocate memory that is to be used and released right away. -** This routine is similar to alloca() in that it is not intended -** for situations where the memory might be held long-term. This -** routine is intended to get memory to old large transient data -** structures that would not normally fit on the stack of an -** embedded processor. -*/ -SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){ - void *p; - assert( n>0 ); - - sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n); - if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ - p = mem0.pScratchFree; - mem0.pScratchFree = mem0.pScratchFree->pNext; - mem0.nScratchFree--; - sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1); - sqlite3_mutex_leave(mem0.mutex); - }else{ - sqlite3_mutex_leave(mem0.mutex); - p = sqlite3Malloc(n); - if( sqlite3GlobalConfig.bMemstat && p ){ - sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); - sqlite3_mutex_leave(mem0.mutex); - } - sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); - } - assert( sqlite3_mutex_notheld(mem0.mutex) ); - - -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) - /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch - ** buffers per thread. - ** - ** This can only be checked in single-threaded mode. - */ - assert( scratchAllocOut==0 ); - if( p ) scratchAllocOut++; -#endif - - return p; -} -SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ - if( p ){ - -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) - /* Verify that no more than two scratch allocation per thread - ** is outstanding at one time. (This is only checked in the - ** single-threaded case since checking in the multi-threaded case - ** would be much more complicated.) */ - assert( scratchAllocOut>=1 && scratchAllocOut<=2 ); - scratchAllocOut--; -#endif - - if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){ - /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */ - ScratchFreeslot *pSlot; - pSlot = (ScratchFreeslot*)p; - sqlite3_mutex_enter(mem0.mutex); - pSlot->pNext = mem0.pScratchFree; - mem0.pScratchFree = pSlot; - mem0.nScratchFree++; - assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch ); - sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1); - sqlite3_mutex_leave(mem0.mutex); - }else{ - /* Release memory back to the heap */ - assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); - assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) ); - sqlite3MemdebugSetType(p, MEMTYPE_HEAP); - if( sqlite3GlobalConfig.bMemstat ){ - int iSize = sqlite3MallocSize(p); - sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize); - sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize); - sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); - sqlite3GlobalConfig.m.xFree(p); - sqlite3_mutex_leave(mem0.mutex); - }else{ - sqlite3GlobalConfig.m.xFree(p); - } - } - } -} - -/* ** TRUE if p is a lookaside memory allocation from db */ #ifndef SQLITE_OMIT_LOOKASIDE @@ -24707,7 +25184,6 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){ #endif pBuf->pNext = db->lookaside.pFree; db->lookaside.pFree = pBuf; - db->lookaside.nOut--; return; } } @@ -24868,16 +25344,16 @@ SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){ assert( db->mallocFailed==0 ); if( n>db->lookaside.sz ){ db->lookaside.anStat[1]++; - }else if( (pBuf = db->lookaside.pFree)==0 ){ - db->lookaside.anStat[2]++; - }else{ + }else if( (pBuf = db->lookaside.pFree)!=0 ){ db->lookaside.pFree = pBuf->pNext; - db->lookaside.nOut++; db->lookaside.anStat[0]++; - if( db->lookaside.nOut>db->lookaside.mxOut ){ - db->lookaside.mxOut = db->lookaside.nOut; - } return (void*)pBuf; + }else if( (pBuf = db->lookaside.pInit)!=0 ){ + db->lookaside.pInit = pBuf->pNext; + db->lookaside.anStat[0]++; + return (void*)pBuf; + }else{ + db->lookaside.anStat[2]++; } }else if( db->mallocFailed ){ return 0; @@ -25715,7 +26191,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( precision>=0 ){ for(length=0; length<precision && bufpt[length]; length++){} }else{ - length = sqlite3Strlen30(bufpt); + length = 0x7fffffff & (int)strlen(bufpt); } break; case etSQLESCAPE: /* Escape ' characters */ @@ -25841,7 +26317,6 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ }else{ char *zOld = isMalloced(p) ? p->zText : 0; i64 szNew = p->nChar; - assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); szNew += N + 1; if( szNew+p->nChar<=p->mxAlloc ){ /* Force exponential buffer size growth as long as it does not overflow, @@ -25883,7 +26358,6 @@ SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){ if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ return; } - assert( (p->zText==p->zBase)==!isMalloced(p) ); while( (N--)>0 ) p->zText[p->nChar++] = c; } @@ -25901,7 +26375,6 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ memcpy(&p->zText[p->nChar], z, N); p->nChar += N; } - assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); } /* @@ -25936,19 +26409,20 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ ** pointer if any kind of error was encountered. */ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ + char *zText; assert( p->mxAlloc>0 && !isMalloced(p) ); - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); - if( p->zText ){ - memcpy(p->zText, p->zBase, p->nChar+1); + zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( zText ){ + memcpy(zText, p->zText, p->nChar+1); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ setStrAccumError(p, STRACCUM_NOMEM); } - return p->zText; + p->zText = zText; + return zText; } SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ - assert( (p->zText==p->zBase)==!isMalloced(p) ); p->zText[p->nChar] = 0; if( p->mxAlloc>0 && !isMalloced(p) ){ return strAccumFinishRealloc(p); @@ -25961,7 +26435,6 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ ** Reset an StrAccum string. Reclaim all malloced memory. */ SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ - assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); if( isMalloced(p) ){ sqlite3DbFree(p->db, p->zText); p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; @@ -25984,11 +26457,11 @@ SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ ** allocations will ever occur. */ SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ - p->zText = p->zBase = zBase; + p->zText = zBase; p->db = db; - p->nChar = 0; p->nAlloc = n; p->mxAlloc = mx; + p->nChar = 0; p->accError = 0; p->printfFlags = 0; } @@ -26557,17 +27030,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: { - sqlite3TreeViewLine(pView, "EXISTS-expr"); + sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags); sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); break; } case TK_SELECT: { - sqlite3TreeViewLine(pView, "SELECT-expr"); + sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags); sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); break; } case TK_IN: { - sqlite3TreeViewLine(pView, "IN"); + sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); @@ -27455,7 +27928,9 @@ translate_out: #endif return SQLITE_OK; } +#endif /* SQLITE_OMIT_UTF16 */ +#ifndef SQLITE_OMIT_UTF16 /* ** This routine checks for a byte-order mark at the beginning of the ** UTF-16 string stored in *pMem. If one is present, it is removed and @@ -28147,7 +28622,11 @@ do_atof_calc: if( esign<0 ){ result = 0.0*s; }else{ +#ifdef INFINITY + result = INFINITY*s; +#else result = 1e308*1e308*s; /* Infinity */ +#endif } } }else{ @@ -28209,16 +28688,12 @@ static int compare2pow63(const char *zNum, int incr){ ** Convert zNum to a 64-bit signed integer. zNum must be decimal. This ** routine does *not* accept hexadecimal notation. ** -** If the zNum value is representable as a 64-bit twos-complement -** integer, then write that value into *pNum and return 0. -** -** If zNum is exactly 9223372036854775808, return 2. This special -** case is broken out because while 9223372036854775808 cannot be a -** signed 64-bit integer, its negative -9223372036854775808 can be. +** Returns: ** -** If zNum is too big for a 64-bit integer and is not -** 9223372036854775808 or if zNum contains any non-numeric text, -** then return 1. +** 0 Successful transformation. Fits in a 64-bit signed integer. +** 1 Excess text after the integer value +** 2 Integer too large for a 64-bit signed integer or is malformed +** 3 Special case of 9223372036854775808 ** ** length is the number of bytes in the string (bytes, not characters). ** The string is not necessarily zero-terminated. The encoding is @@ -28231,6 +28706,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc int i; int c = 0; int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */ + int rc; /* Baseline return code */ const char *zStart; const char *zEnd = zNum + length; assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); @@ -28270,31 +28746,35 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc testcase( i==20 ); if( &zNum[i]<zEnd /* Extra bytes at the end */ || (i==0 && zStart==zNum) /* No digits */ - || i>19*incr /* Too many digits */ || nonNum /* UTF16 with high-order bytes non-zero */ ){ + rc = 1; + }else{ + rc = 0; + } + if( i>19*incr ){ /* Too many digits */ /* zNum is empty or contains non-numeric text or is longer ** than 19 digits (thus guaranteeing that it is too large) */ - return 1; + return 2; }else if( i<19*incr ){ /* Less than 19 digits, so we know that it fits in 64 bits */ assert( u<=LARGEST_INT64 ); - return 0; + return rc; }else{ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ c = compare2pow63(zNum, incr); if( c<0 ){ /* zNum is less than 9223372036854775808 so it fits */ assert( u<=LARGEST_INT64 ); - return 0; + return rc; }else if( c>0 ){ /* zNum is greater than 9223372036854775808 so it overflows */ - return 1; + return 2; }else{ /* zNum is exactly 9223372036854775808. Fits if negative. The ** special case 2 overflow if positive */ assert( u-1==LARGEST_INT64 ); - return neg ? 0 : 2; + return neg ? rc : 3; } } } @@ -28307,8 +28787,9 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc ** Returns: ** ** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Integer too large for a 64-bit signed integer or is malformed -** 2 Special case of 9223372036854775808 +** 1 Excess text after the integer value +** 2 Integer too large for a 64-bit signed integer or is malformed +** 3 Special case of 9223372036854775808 */ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){ #ifndef SQLITE_OMIT_HEX_INTEGER @@ -28322,7 +28803,7 @@ 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 : 1; + return (z[k]==0 && k-i<=16) ? 0 : 2; }else #endif /* SQLITE_OMIT_HEX_INTEGER */ { @@ -28932,7 +29413,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ ** overflow, leave *pA unchanged and return 1. */ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 +#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) return __builtin_add_overflow(*pA, iB, pA); #else i64 iA = *pA; @@ -28952,7 +29433,7 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ #endif } SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 +#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) return __builtin_sub_overflow(*pA, iB, pA); #else testcase( iB==SMALLEST_INT64+1 ); @@ -28967,7 +29448,7 @@ SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ #endif } SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 +#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER) return __builtin_mul_overflow(*pA, iB, pA); #else i64 iA = *pA; @@ -29069,8 +29550,14 @@ SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ if( x<2 ) return 0; while( x<8 ){ y -= 10; x <<= 1; } }else{ +#if GCC_VERSION>=5004000 + int i = 60 - __builtin_clzll(x); + y += i*10; + x >>= i; +#else while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/ while( x>15 ){ y += 10; x >>= 1; } +#endif } return a[x&7] + y - 10; } @@ -29366,8 +29853,9 @@ static int rehash(Hash *pH, unsigned int new_size){ } /* This function (for internal use only) locates an element in an -** hash table that matches the given key. The hash for this key is -** also computed and returned in the *pH parameter. +** hash table that matches the given key. If no element is found, +** a pointer to a static null element with HashElem.data==0 is returned. +** If pH is not NULL, then the hash for this key is written to *pH. */ static HashElem *findElementWithHash( const Hash *pH, /* The pH to be searched */ @@ -29377,6 +29865,7 @@ static HashElem *findElementWithHash( HashElem *elem; /* Used to loop thru the element list */ int count; /* Number of elements left to test */ unsigned int h; /* The computed hash */ + static HashElem nullElement = { 0, 0, 0, 0 }; if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ struct _ht *pEntry; @@ -29389,7 +29878,7 @@ static HashElem *findElementWithHash( elem = pH->first; count = pH->count; } - *pHash = h; + if( pHash ) *pHash = h; while( count-- ){ assert( elem!=0 ); if( sqlite3StrICmp(elem->pKey,pKey)==0 ){ @@ -29397,7 +29886,7 @@ static HashElem *findElementWithHash( } elem = elem->next; } - return 0; + return &nullElement; } /* Remove a single entry from the hash table given a pointer to that @@ -29439,13 +29928,9 @@ static void removeElementGivenHash( ** found, or NULL if there is no match. */ SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){ - HashElem *elem; /* The element that matches key */ - unsigned int h; /* A hash on key */ - assert( pH!=0 ); assert( pKey!=0 ); - elem = findElementWithHash(pH, pKey, &h); - return elem ? elem->data : 0; + return findElementWithHash(pH, pKey, 0)->data; } /* Insert an element into the hash table pH. The key is pKey @@ -29470,7 +29955,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){ assert( pH!=0 ); assert( pKey!=0 ); elem = findElementWithHash(pH,pKey,&h); - if( elem ){ + if( elem->data ){ void *old_data = elem->data; if( data==0 ){ removeElementGivenHash(pH,elem,h); @@ -29553,47 +30038,47 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"), /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"), /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), - /* 43 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), - /* 44 */ "Program" OpHelp(""), - /* 45 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), - /* 46 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), - /* 47 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), - /* 48 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 49 */ "IncrVacuum" OpHelp(""), - /* 50 */ "VNext" OpHelp(""), - /* 51 */ "Init" OpHelp("Start at P2"), - /* 52 */ "Return" OpHelp(""), - /* 53 */ "EndCoroutine" OpHelp(""), - /* 54 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 55 */ "Halt" OpHelp(""), - /* 56 */ "Integer" OpHelp("r[P2]=P1"), - /* 57 */ "Int64" OpHelp("r[P2]=P4"), - /* 58 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 59 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 60 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 61 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 62 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 63 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 64 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 65 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 66 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 67 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 68 */ "CollSeq" OpHelp(""), - /* 69 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 70 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), - /* 71 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), - /* 72 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 73 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 74 */ "RealAffinity" OpHelp(""), - /* 75 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"), - /* 76 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"), - /* 77 */ "Ne" OpHelp("IF r[P3]!=r[P1]"), - /* 78 */ "Eq" OpHelp("IF r[P3]==r[P1]"), - /* 79 */ "Gt" OpHelp("IF r[P3]>r[P1]"), - /* 80 */ "Le" OpHelp("IF r[P3]<=r[P1]"), - /* 81 */ "Lt" OpHelp("IF r[P3]<r[P1]"), - /* 82 */ "Ge" OpHelp("IF r[P3]>=r[P1]"), - /* 83 */ "ElseNotEq" OpHelp(""), + /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"), + /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"), + /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 46 */ "Program" OpHelp(""), + /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), + /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), + /* 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]"), + /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"), + /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"), + /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"), + /* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"), + /* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"), + /* 58 */ "ElseNotEq" OpHelp(""), + /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 60 */ "IncrVacuum" OpHelp(""), + /* 61 */ "VNext" OpHelp(""), + /* 62 */ "Init" OpHelp("Start at P2"), + /* 63 */ "Return" OpHelp(""), + /* 64 */ "EndCoroutine" OpHelp(""), + /* 65 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 66 */ "Halt" OpHelp(""), + /* 67 */ "Integer" OpHelp("r[P2]=P1"), + /* 68 */ "Int64" OpHelp("r[P2]=P4"), + /* 69 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 70 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 71 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 72 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 73 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 74 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 75 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 76 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 77 */ "IntCopy" OpHelp("r[P2]=r[P1]"), + /* 78 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 79 */ "CollSeq" OpHelp(""), + /* 80 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 81 */ "RealAffinity" OpHelp(""), + /* 82 */ "Cast" OpHelp("affinity(r[P1])"), + /* 83 */ "Permutation" OpHelp(""), /* 84 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), /* 85 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), /* 86 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"), @@ -29604,78 +30089,80 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 91 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), /* 92 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 94 */ "Cast" OpHelp("affinity(r[P1])"), + /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), - /* 96 */ "Permutation" OpHelp(""), + /* 96 */ "Column" OpHelp("r[P3]=PX"), /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 99 */ "Column" OpHelp("r[P3]=PX"), - /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 102 */ "Count" OpHelp("r[P2]=count()"), - /* 103 */ "ReadCookie" OpHelp(""), - /* 104 */ "SetCookie" OpHelp(""), - /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 108 */ "OpenDup" OpHelp(""), - /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 111 */ "SorterOpen" OpHelp(""), - /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 114 */ "Close" OpHelp(""), - /* 115 */ "ColumnsUsed" OpHelp(""), - /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 120 */ "Delete" OpHelp(""), - /* 121 */ "ResetCount" OpHelp(""), - /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 123 */ "SorterData" OpHelp("r[P2]=data"), - /* 124 */ "RowData" OpHelp("r[P2]=data"), - /* 125 */ "Rowid" OpHelp("r[P2]=rowid"), - /* 126 */ "NullRow" OpHelp(""), - /* 127 */ "SorterInsert" OpHelp("key=r[P2]"), - /* 128 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 129 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 130 */ "Seek" OpHelp("Move P3 to P1.rowid"), - /* 131 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 100 */ "Count" OpHelp("r[P2]=count()"), + /* 101 */ "ReadCookie" OpHelp(""), + /* 102 */ "SetCookie" OpHelp(""), + /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 106 */ "OpenDup" OpHelp(""), + /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 109 */ "SorterOpen" OpHelp(""), + /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 112 */ "Close" OpHelp(""), + /* 113 */ "ColumnsUsed" OpHelp(""), + /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 118 */ "Delete" OpHelp(""), + /* 119 */ "ResetCount" OpHelp(""), + /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 121 */ "SorterData" OpHelp("r[P2]=data"), + /* 122 */ "RowData" OpHelp("r[P2]=data"), + /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 124 */ "NullRow" OpHelp(""), + /* 125 */ "SeekEnd" OpHelp(""), + /* 126 */ "SorterInsert" OpHelp("key=r[P2]"), + /* 127 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 128 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 129 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), + /* 130 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 131 */ "Destroy" OpHelp(""), /* 132 */ "Real" OpHelp("r[P2]=P4"), - /* 133 */ "Destroy" OpHelp(""), - /* 134 */ "Clear" OpHelp(""), - /* 135 */ "ResetSorter" OpHelp(""), - /* 136 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), - /* 137 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), - /* 138 */ "SqlExec" OpHelp(""), - /* 139 */ "ParseSchema" OpHelp(""), - /* 140 */ "LoadAnalysis" OpHelp(""), - /* 141 */ "DropTable" OpHelp(""), - /* 142 */ "DropIndex" OpHelp(""), - /* 143 */ "DropTrigger" OpHelp(""), - /* 144 */ "IntegrityCk" OpHelp(""), - /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 146 */ "Param" OpHelp(""), - /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 153 */ "Expire" OpHelp(""), - /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 155 */ "VBegin" OpHelp(""), - /* 156 */ "VCreate" OpHelp(""), - /* 157 */ "VDestroy" OpHelp(""), - /* 158 */ "VOpen" OpHelp(""), - /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 160 */ "VRename" OpHelp(""), - /* 161 */ "Pagecount" OpHelp(""), - /* 162 */ "MaxPgcnt" OpHelp(""), - /* 163 */ "CursorHint" OpHelp(""), - /* 164 */ "Noop" OpHelp(""), - /* 165 */ "Explain" OpHelp(""), + /* 133 */ "Clear" OpHelp(""), + /* 134 */ "ResetSorter" OpHelp(""), + /* 135 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), + /* 136 */ "SqlExec" OpHelp(""), + /* 137 */ "ParseSchema" OpHelp(""), + /* 138 */ "LoadAnalysis" OpHelp(""), + /* 139 */ "DropTable" OpHelp(""), + /* 140 */ "DropIndex" OpHelp(""), + /* 141 */ "DropTrigger" OpHelp(""), + /* 142 */ "IntegrityCk" OpHelp(""), + /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 144 */ "Param" OpHelp(""), + /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 151 */ "Expire" OpHelp(""), + /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 153 */ "VBegin" OpHelp(""), + /* 154 */ "VCreate" OpHelp(""), + /* 155 */ "VDestroy" OpHelp(""), + /* 156 */ "VOpen" OpHelp(""), + /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 158 */ "VRename" OpHelp(""), + /* 159 */ "Pagecount" OpHelp(""), + /* 160 */ "MaxPgcnt" OpHelp(""), + /* 161 */ "PureFunc0" OpHelp(""), + /* 162 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 163 */ "PureFunc" OpHelp(""), + /* 164 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 165 */ "CursorHint" OpHelp(""), + /* 166 */ "Noop" OpHelp(""), + /* 167 */ "Explain" OpHelp(""), }; return azName[i]; } @@ -29775,6 +30262,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <sys/ioctl.h> #include <unistd.h> /* #include <time.h> */ #include <sys/time.h> @@ -29784,7 +30272,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ #endif #if SQLITE_ENABLE_LOCKING_STYLE -# include <sys/ioctl.h> +/* # include <sys/ioctl.h> */ # include <sys/file.h> # include <sys/param.h> #endif /* SQLITE_ENABLE_LOCKING_STYLE */ @@ -29894,7 +30382,7 @@ struct unixFile { unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ - UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ + UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ @@ -29905,10 +30393,8 @@ struct unixFile { sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ void *pMapRegion; /* Memory mapped region */ #endif -#ifdef __QNXNTO__ int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ -#endif #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif @@ -30211,6 +30697,20 @@ SQLITE_API extern int sqlite3_open_file_count; # define lseek lseek64 #endif +#ifdef __linux__ +/* +** Linux-specific IOCTL magic numbers used for controlling F2FS +*/ +#define F2FS_IOCTL_MAGIC 0xf5 +#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1) +#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2) +#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3) +#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5) +#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32) +#define F2FS_FEATURE_ATOMIC_WRITE 0x0004 +#endif /* __linux__ */ + + /* ** Different Unix systems declare open() in different ways. Same use ** open(const char*,int,mode_t). Others use open(const char*,int,...). @@ -30383,6 +30883,9 @@ static struct unix_syscall { #endif #define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent) + { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 }, +#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent) + }; /* End of the overrideable system calls */ @@ -30987,7 +31490,8 @@ struct unixInodeInfo { /* ** A lists of all unixInodeInfo objects. */ -static unixInodeInfo *inodeList = 0; +static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ +static unsigned int nUnusedFd = 0; /* Total unused file descriptors */ /* ** @@ -31097,6 +31601,7 @@ static void closePendingFds(unixFile *pFile){ pNext = p->pNext; robust_close(pFile, p->fd, __LINE__); sqlite3_free(p); + nUnusedFd--; } pInode->pUnused = 0; } @@ -31129,6 +31634,7 @@ static void releaseInodeInfo(unixFile *pFile){ sqlite3_free(pInode); } } + assert( inodeList!=0 || nUnusedFd==0 ); } /* @@ -31198,6 +31704,7 @@ static int findInodeInfo( #else fileId.ino = (u64)statbuf.st_ino; #endif + assert( inodeList!=0 || nUnusedFd==0 ); pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ pInode = pInode->pNext; @@ -31617,11 +32124,12 @@ end_lock: */ static void setPendingFd(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; - UnixUnusedFd *p = pFile->pUnused; + UnixUnusedFd *p = pFile->pPreallocatedUnused; p->pNext = pInode->pUnused; pInode->pUnused = p; pFile->h = -1; - pFile->pUnused = 0; + pFile->pPreallocatedUnused = 0; + nUnusedFd++; } /* @@ -31846,7 +32354,7 @@ static int closeUnixFile(sqlite3_file *id){ #endif OSTRACE(("CLOSE %-3d\n", pFile->h)); OpenCounter(-1); - sqlite3_free(pFile->pUnused); + sqlite3_free(pFile->pPreallocatedUnused); memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } @@ -32183,7 +32691,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved)); #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ + if( (rc & 0xff) == SQLITE_IOERR ){ rc = SQLITE_OK; reserved=1; } @@ -32250,7 +32758,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) { OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), rc==SQLITE_OK ? "ok" : "failed")); #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS - if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ + if( (rc & 0xff) == SQLITE_IOERR ){ rc = SQLITE_BUSY; } #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ @@ -32787,7 +33295,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ /* Can't reestablish the shared lock. Sqlite can't deal, this is ** a critical I/O error */ - rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : + rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 : SQLITE_IOERR_LOCK; goto afp_end_lock; } @@ -33067,7 +33575,7 @@ static int unixRead( /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 - assert( pFile->pUnused==0 + assert( pFile->pPreallocatedUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); @@ -33180,7 +33688,7 @@ static int unixWrite( /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ #if 0 - assert( pFile->pUnused==0 + assert( pFile->pPreallocatedUnused==0 || offset>=PENDING_BYTE+512 || offset+amt<=PENDING_BYTE ); @@ -33660,6 +34168,21 @@ static int unixGetTempname(int nBuf, char *zBuf); static int unixFileControl(sqlite3_file *id, int op, void *pArg){ unixFile *pFile = (unixFile*)id; switch( op ){ +#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: { + int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE); + return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK; + } + case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: { + int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE); + return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK; + } + case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: { + int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE); + return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK; + } +#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ + case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = pFile->eFileLock; return SQLITE_OK; @@ -33710,6 +34233,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ if( newLimit>sqlite3GlobalConfig.mxMmap ){ newLimit = sqlite3GlobalConfig.mxMmap; } + + /* The value of newLimit may be eventually cast to (size_t) and passed + ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a + ** 64-bit type. */ + if( newLimit>0 && sizeof(size_t)<8 ){ + newLimit = (newLimit & 0x7FFFFFFF); + } + *(i64*)pArg = pFile->mmapSizeMax; if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ pFile->mmapSizeMax = newLimit; @@ -33743,30 +34274,41 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } /* -** Return the sector size in bytes of the underlying block device for -** the specified file. This is almost always 512 bytes, but may be -** larger for some devices. +** If pFd->sectorSize is non-zero when this function is called, it is a +** no-op. Otherwise, the values of pFd->sectorSize and +** pFd->deviceCharacteristics are set according to the file-system +** characteristics. ** -** SQLite code assumes this function cannot fail. It also assumes that -** if two files are created in the same file-system directory (i.e. -** a database and its journal file) that the sector size will be the -** same for both. +** There are two versions of this function. One for QNX and one for all +** other systems. */ -#ifndef __QNXNTO__ -static int unixSectorSize(sqlite3_file *NotUsed){ - UNUSED_PARAMETER(NotUsed); - return SQLITE_DEFAULT_SECTOR_SIZE; -} -#endif +#ifndef __QNXNTO__ +static void setDeviceCharacteristics(unixFile *pFd){ + assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 ); + if( pFd->sectorSize==0 ){ +#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + int res; + u32 f = 0; -/* -** The following version of unixSectorSize() is optimized for QNX. -*/ -#ifdef __QNXNTO__ + /* Check for support for F2FS atomic batch writes. */ + res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f); + if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){ + pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC; + } +#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */ + + /* Set the POWERSAFE_OVERWRITE flag if requested. */ + if( pFd->ctrlFlags & UNIXFILE_PSOW ){ + pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; + } + + pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; + } +} +#else #include <sys/dcmd_blk.h> #include <sys/statvfs.h> -static int unixSectorSize(sqlite3_file *id){ - unixFile *pFile = (unixFile*)id; +static void setDeviceCharacteristics(unixFile *pFile){ if( pFile->sectorSize == 0 ){ struct statvfs fsInfo; @@ -33835,9 +34377,24 @@ static int unixSectorSize(sqlite3_file *id){ pFile->deviceCharacteristics = 0; pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; } - return pFile->sectorSize; } -#endif /* __QNXNTO__ */ +#endif + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int unixSectorSize(sqlite3_file *id){ + unixFile *pFd = (unixFile*)id; + setDeviceCharacteristics(pFd); + return pFd->sectorSize; +} /* ** Return the device characteristics for the file. @@ -33853,16 +34410,9 @@ static int unixSectorSize(sqlite3_file *id){ ** available to turn it off and URI query parameter available to turn it off. */ static int unixDeviceCharacteristics(sqlite3_file *id){ - unixFile *p = (unixFile*)id; - int rc = 0; -#ifdef __QNXNTO__ - if( p->sectorSize==0 ) unixSectorSize(id); - rc = p->deviceCharacteristics; -#endif - if( p->ctrlFlags & UNIXFILE_PSOW ){ - rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; - } - return rc; + unixFile *pFd = (unixFile*)id; + setDeviceCharacteristics(pFd); + return pFd->deviceCharacteristics; } #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 @@ -35120,17 +35670,6 @@ static int fillInUnixFile( assert( pNew->pInode==NULL ); - /* Usually the path zFilename should not be a relative pathname. The - ** exception is when opening the proxy "conch" file in builds that - ** include the special Apple locking styles. - */ -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE - assert( zFilename==0 || zFilename[0]=='/' - || pVfs->pAppData==(void*)&autolockIoFinder ); -#else - assert( zFilename==0 || zFilename[0]=='/' ); -#endif - /* No locking occurs in temporary files */ assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 ); @@ -35389,6 +35928,8 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ #if !OS_VXWORKS struct stat sStat; /* Results of stat() call */ + unixEnterMutex(); + /* A stat() call may fail for various reasons. If this happens, it is ** almost certain that an open() call on the same path will also fail. ** For this reason, if an error occurs in the stat() call here, it is @@ -35397,10 +35938,9 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ ** ** Even if a subsequent open() call does succeed, the consequences of ** not searching for a reusable file descriptor are not dire. */ - if( 0==osStat(zPath, &sStat) ){ + if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){ unixInodeInfo *pInode; - unixEnterMutex(); pInode = inodeList; while( pInode && (pInode->fileId.dev!=sStat.st_dev || pInode->fileId.ino!=(u64)sStat.st_ino) ){ @@ -35411,11 +35951,12 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); pUnused = *pp; if( pUnused ){ + nUnusedFd--; *pp = pUnused->pNext; } } - unixLeaveMutex(); } + unixLeaveMutex(); #endif /* if !OS_VXWORKS */ return pUnused; } @@ -35491,16 +36032,11 @@ static int findCreateFileMode( */ nDb = sqlite3Strlen30(zPath) - 1; while( zPath[nDb]!='-' ){ -#ifndef SQLITE_ENABLE_8_3_NAMES - /* In the normal case (8+3 filenames disabled) the journal filename - ** is guaranteed to contain a '-' character. */ - assert( nDb>0 ); - assert( sqlite3Isalnum(zPath[nDb]) ); -#else - /* If 8+3 names are possible, then the journal file might not contain - ** a '-' character. So check for that case and return early. */ + /* In normal operation, the journal file name will always contain + ** a '-' character. However in 8+3 filename mode, or if a corrupt + ** rollback journal specifies a master journal with a goofy name, then + ** the '-' might be missing. */ if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK; -#endif nDb--; } memcpy(zDb, zPath, nDb); @@ -35636,7 +36172,7 @@ static int unixOpen( return SQLITE_NOMEM_BKPT; } } - p->pUnused = pUnused; + p->pPreallocatedUnused = pUnused; /* Database filenames are double-zero terminated if they are not ** URIs with parameters. Hence, they can always be passed into @@ -35673,7 +36209,7 @@ static int unixOpen( gid_t gid; /* Groupid for the file */ rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ - assert( !p->pUnused ); + assert( !p->pPreallocatedUnused ); assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); return rc; } @@ -35707,9 +36243,9 @@ static int unixOpen( *pOutFlags = flags; } - if( p->pUnused ){ - p->pUnused->fd = fd; - p->pUnused->flags = flags; + if( p->pPreallocatedUnused ){ + p->pPreallocatedUnused->fd = fd; + p->pPreallocatedUnused->flags = flags; } if( isDelete ){ @@ -35786,11 +36322,14 @@ static int unixOpen( } #endif + assert( zPath==0 || zPath[0]=='/' + || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL + ); rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); open_finished: if( rc!=SQLITE_OK ){ - sqlite3_free(p->pUnused); + sqlite3_free(p->pPreallocatedUnused); } return rc; } @@ -36531,7 +37070,7 @@ static int proxyCreateUnixFile( dummyVfs.zName = "dummy"; pUnused->fd = fd; pUnused->flags = openFlags; - pNew->pUnused = pUnused; + pNew->pPreallocatedUnused = pUnused; rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); if( rc==SQLITE_OK ){ @@ -37481,7 +38020,7 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==28 ); + assert( ArraySize(aSyscall)==29 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ @@ -41264,6 +41803,14 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){ if( newLimit>sqlite3GlobalConfig.mxMmap ){ newLimit = sqlite3GlobalConfig.mxMmap; } + + /* The value of newLimit may be eventually cast to (SIZE_T) and passed + ** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at + ** least a 64-bit type. */ + if( newLimit>0 && sizeof(SIZE_T)<8 ){ + newLimit = (newLimit & 0x7FFFFFFF); + } + *(i64*)pArg = pFile->mmapSizeMax; if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ pFile->mmapSizeMax = newLimit; @@ -42576,6 +43123,14 @@ static int winIsDir(const void *zConverted){ return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); } +/* forward reference */ +static int winAccess( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to check */ + int flags, /* Type of test to make on this file */ + int *pResOut /* OUT: Result */ +); + /* ** Open a file. */ @@ -42752,37 +43307,52 @@ static int winOpen( extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; extendedParameters.lpSecurityAttributes = NULL; extendedParameters.hTemplateFile = NULL; - while( (h = osCreateFile2((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, - dwCreationDisposition, - &extendedParameters))==INVALID_HANDLE_VALUE && - winRetryIoerr(&cnt, &lastErrno) ){ - /* Noop */ - } + do{ + h = osCreateFile2((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + &extendedParameters); + if( h!=INVALID_HANDLE_VALUE ) break; + if( isReadWrite ){ + int isRO = 0; + int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + if( rc2==SQLITE_OK && isRO ) break; + } + }while( winRetryIoerr(&cnt, &lastErrno) ); #else - while( (h = osCreateFileW((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL))==INVALID_HANDLE_VALUE && - winRetryIoerr(&cnt, &lastErrno) ){ - /* Noop */ - } + do{ + h = osCreateFileW((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL); + if( h!=INVALID_HANDLE_VALUE ) break; + if( isReadWrite ){ + int isRO = 0; + int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + if( rc2==SQLITE_OK && isRO ) break; + } + }while( winRetryIoerr(&cnt, &lastErrno) ); #endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ - while( (h = osCreateFileA((LPCSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL))==INVALID_HANDLE_VALUE && - winRetryIoerr(&cnt, &lastErrno) ){ - /* Noop */ - } + do{ + h = osCreateFileA((LPCSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL); + if( h!=INVALID_HANDLE_VALUE ) break; + if( isReadWrite ){ + int isRO = 0; + int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); + if( rc2==SQLITE_OK && isRO ) break; + } + }while( winRetryIoerr(&cnt, &lastErrno) ); } #endif winLogIoerr(cnt, __LINE__); @@ -42791,8 +43361,6 @@ static int winOpen( dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); if( h==INVALID_HANDLE_VALUE ){ - pFile->lastErrno = lastErrno; - winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); sqlite3_free(zConverted); sqlite3_free(zTmpname); if( isReadWrite && !isExclusive ){ @@ -42801,6 +43369,8 @@ static int winOpen( ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags); }else{ + pFile->lastErrno = lastErrno; + winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); return SQLITE_CANTOPEN_BKPT; } } @@ -43393,9 +43963,6 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ EntropyGatherer e; UNUSED_PARAMETER(pVfs); memset(zBuf, 0, nBuf); -#if defined(_MSC_VER) && _MSC_VER>=1400 && !SQLITE_OS_WINCE - rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */ -#endif /* defined(_MSC_VER) && _MSC_VER>=1400 */ e.a = (unsigned char*)zBuf; e.na = nBuf; e.nXor = 0; @@ -44314,12 +44881,9 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ p->eCreate = 2; } } - pPage->pDirtyNext = 0; - pPage->pDirtyPrev = 0; } if( addRemove & PCACHE_DIRTYLIST_ADD ){ - assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); - + pPage->pDirtyPrev = 0; pPage->pDirtyNext = p->pDirty; if( pPage->pDirtyNext ){ assert( pPage->pDirtyNext->pDirtyPrev==0 ); @@ -44636,11 +45200,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){ if( (--p->nRef)==0 ){ if( p->flags&PGHDR_CLEAN ){ pcacheUnpin(p); - }else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/ - /* Move the page to the head of the dirty list. If p->pDirtyPrev==0, - ** then page p is already at the head of the dirty list and the - ** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE - ** tag above. */ + }else{ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); } } @@ -45101,7 +45661,6 @@ typedef struct PGroup PGroup; struct PgHdr1 { sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */ unsigned int iKey; /* Key value (page number) */ - u8 isPinned; /* Page in use, not on the LRU list */ u8 isBulkLocal; /* This page from bulk local storage */ u8 isAnchor; /* This is the PGroup.lru element */ PgHdr1 *pNext; /* Next in hash table chain */ @@ -45110,6 +45669,12 @@ struct PgHdr1 { PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ }; +/* +** A page is pinned if it is no on the LRU list +*/ +#define PAGE_IS_PINNED(p) ((p)->pLruNext==0) +#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) + /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set ** of one or more PCaches that are able to recycle each other's unpinned ** pages when they are under memory pressure. A PGroup is an instance of @@ -45137,7 +45702,7 @@ struct PGroup { unsigned int nMaxPage; /* Sum of nMax for purgeable caches */ unsigned int nMinPage; /* Sum of nMin for purgeable caches */ unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */ - unsigned int nCurrentPage; /* Number of purgeable pages allocated */ + unsigned int nPurgeable; /* Number of purgeable pages allocated */ PgHdr1 lru; /* The beginning and end of the LRU list */ }; @@ -45151,11 +45716,13 @@ struct PGroup { */ struct PCache1 { /* Cache configuration parameters. Page size (szPage) and the purgeable - ** flag (bPurgeable) are set when the cache is created. nMax may be + ** flag (bPurgeable) and the pnPurgeable pointer are all set when the + ** cache is created and are never changed thereafter. nMax may be ** modified at any time by a call to the pcache1Cachesize() method. ** The PGroup mutex must be held when accessing nMax. */ PGroup *pGroup; /* PGroup this cache belongs to */ + unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */ int szPage; /* Size of database content section */ int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */ int szAlloc; /* Total size of one pcache line */ @@ -45250,6 +45817,7 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ if( pcache1.isInit ){ PgFreeslot *p; if( pBuf==0 ) sz = n = 0; + if( n==0 ) sz = 0; sz = ROUNDDOWN8(sz); pcache1.szSlot = sz; pcache1.nSlot = pcache1.nFreeSlot = n; @@ -45442,9 +46010,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){ p->isBulkLocal = 0; p->isAnchor = 0; } - if( pCache->bPurgeable ){ - pCache->pGroup->nCurrentPage++; - } + (*pCache->pnPurgeable)++; return p; } @@ -45465,9 +46031,7 @@ static void pcache1FreePage(PgHdr1 *p){ sqlite3_free(p); #endif } - if( pCache->bPurgeable ){ - pCache->pGroup->nCurrentPage--; - } + (*pCache->pnPurgeable)--; } /* @@ -45562,22 +46126,18 @@ static void pcache1ResizeHash(PCache1 *p){ ** The PGroup mutex must be held when this function is called. */ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){ - PCache1 *pCache; - assert( pPage!=0 ); - assert( pPage->isPinned==0 ); - pCache = pPage->pCache; + assert( PAGE_IS_UNPINNED(pPage) ); assert( pPage->pLruNext ); assert( pPage->pLruPrev ); - assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); + assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) ); pPage->pLruPrev->pLruNext = pPage->pLruNext; pPage->pLruNext->pLruPrev = pPage->pLruPrev; pPage->pLruNext = 0; pPage->pLruPrev = 0; - pPage->isPinned = 1; assert( pPage->isAnchor==0 ); - assert( pCache->pGroup->lru.isAnchor==1 ); - pCache->nRecyclable--; + assert( pPage->pCache->pGroup->lru.isAnchor==1 ); + pPage->pCache->nRecyclable--; return pPage; } @@ -45611,11 +46171,11 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){ PGroup *pGroup = pCache->pGroup; PgHdr1 *p; assert( sqlite3_mutex_held(pGroup->mutex) ); - while( pGroup->nCurrentPage>pGroup->nMaxPage + while( pGroup->nPurgeable>pGroup->nMaxPage && (p=pGroup->lru.pLruPrev)->isAnchor==0 ){ assert( p->pCache->pGroup==pGroup ); - assert( p->isPinned==0 ); + assert( PAGE_IS_UNPINNED(p) ); pcache1PinPage(p); pcache1RemoveFromHash(p, 1); } @@ -45664,7 +46224,7 @@ static void pcache1TruncateUnsafe( if( pPage->iKey>=iLimit ){ pCache->nPage--; *pp = pPage->pNext; - if( !pPage->isPinned ) pcache1PinPage(pPage); + if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage); pcache1FreePage(pPage); }else{ pp = &pPage->pNext; @@ -45782,6 +46342,10 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){ pCache->nMin = 10; pGroup->nMinPage += pCache->nMin; pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage; + pCache->pnPurgeable = &pGroup->nPurgeable; + }else{ + static unsigned int dummyCurrentPage; + pCache->pnPurgeable = &dummyCurrentPage; } pcache1LeaveMutex(pGroup); if( pCache->nHash==0 ){ @@ -45883,7 +46447,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( ){ PCache1 *pOther; pPage = pGroup->lru.pLruPrev; - assert( pPage->isPinned==0 ); + assert( PAGE_IS_UNPINNED(pPage) ); pcache1RemoveFromHash(pPage, 0); pcache1PinPage(pPage); pOther = pPage->pCache; @@ -45891,7 +46455,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( pcache1FreePage(pPage); pPage = 0; }else{ - pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable); + pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable); } } @@ -45910,7 +46474,6 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2( pPage->pCache = pCache; pPage->pLruPrev = 0; pPage->pLruNext = 0; - pPage->isPinned = 1; *(void **)pPage->page.pExtra = 0; pCache->apHash[h] = pPage; if( iKey>pCache->iMaxKey ){ @@ -45996,7 +46559,7 @@ static PgHdr1 *pcache1FetchNoMutex( ** Otherwise (page not in hash and createFlag!=0) continue with ** subsequent steps to try to create the page. */ if( pPage ){ - if( !pPage->isPinned ){ + if( PAGE_IS_UNPINNED(pPage) ){ return pcache1PinPage(pPage); }else{ return pPage; @@ -46071,9 +46634,9 @@ static void pcache1Unpin( ** part of the PGroup LRU list. */ assert( pPage->pLruPrev==0 && pPage->pLruNext==0 ); - assert( pPage->isPinned==1 ); + assert( PAGE_IS_PINNED(pPage) ); - if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){ + if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){ pcache1RemoveFromHash(pPage, 1); }else{ /* Add the page to the PGroup LRU list. */ @@ -46082,7 +46645,6 @@ static void pcache1Unpin( (pPage->pLruNext = *ppFirst)->pLruPrev = pPage; *ppFirst = pPage; pCache->nRecyclable++; - pPage->isPinned = 0; } pcache1LeaveMutex(pCache->pGroup); @@ -46226,7 +46788,7 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ #ifdef SQLITE_PCACHE_SEPARATE_HEADER nFree += sqlite3MemSize(p); #endif - assert( p->isPinned==0 ); + assert( PAGE_IS_UNPINNED(p) ); pcache1PinPage(p); pcache1RemoveFromHash(p, 1); } @@ -46250,10 +46812,10 @@ SQLITE_PRIVATE void sqlite3PcacheStats( PgHdr1 *p; int nRecyclable = 0; for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){ - assert( p->isPinned==0 ); + assert( PAGE_IS_UNPINNED(p) ); nRecyclable++; } - *pnCurrent = pcache1.grp.nCurrentPage; + *pnCurrent = pcache1.grp.nPurgeable; *pnMax = (int)pcache1.grp.nMaxPage; *pnMin = (int)pcache1.grp.nMinPage; *pnRecyclable = nRecyclable; @@ -46808,11 +47370,11 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 /* #include "sqliteInt.h" */ -/* Additional values that can be added to the sync_flags argument of -** sqlite3WalFrames(): +/* Macros for extracting appropriate sync flags for either transaction +** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)): */ -#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */ -#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ +#define WAL_SYNC_FLAGS(X) ((X)&0x03) +#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03) #ifdef SQLITE_OMIT_WAL # define sqlite3WalOpen(x,y,z) 0 @@ -47045,8 +47607,8 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ ** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file ** struct as its argument. */ -#define PAGERID(p) ((int)(p->fd)) -#define FILEHANDLEID(fd) ((int)fd) +#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd)) +#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd)) /* ** The Pager.eState variable stores the current 'state' of a pager. A @@ -47533,6 +48095,18 @@ struct PagerSavepoint { ** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode ** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX ** sub-codes. +** +** syncFlags, walSyncFlags +** +** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03). +** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode +** and contains the flags used to sync the checkpoint operations in the +** lower two bits, and sync flags used for transaction commits in the WAL +** file in bits 0x04 and 0x08. In other words, to get the correct sync flags +** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct +** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note +** that with synchronous=NORMAL in WAL mode, transaction commit is not synced +** meaning that the 0x04 and 0x08 bits are both zero. */ struct Pager { sqlite3_vfs *pVfs; /* OS functions to use for IO */ @@ -47542,9 +48116,8 @@ struct Pager { u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 extraSync; /* sync directory after journal delete */ - u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ - u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ + u8 walSyncFlags; /* See description above */ u8 tempFile; /* zFilename is a temporary or immutable file */ u8 noLock; /* Do not lock (except in WAL mode) */ u8 readOnly; /* True for a read-only database */ @@ -47864,6 +48437,7 @@ static int assert_pager_state(Pager *p){ assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL + || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) ); assert( pPager->dbOrigSize<=pPager->dbHintSize ); break; @@ -47875,6 +48449,7 @@ static int assert_pager_state(Pager *p){ assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL + || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC) ); break; @@ -48085,34 +48660,47 @@ static int pagerLockDb(Pager *pPager, int eLock){ } /* -** This function determines whether or not the atomic-write optimization -** can be used with this pager. The optimization can be used if: +** This function determines whether or not the atomic-write or +** atomic-batch-write optimizations can be used with this pager. The +** atomic-write optimization can be used if: ** ** (a) the value returned by OsDeviceCharacteristics() indicates that ** a database page may be written atomically, and ** (b) the value returned by OsSectorSize() is less than or equal ** to the page size. ** -** The optimization is also always enabled for temporary files. It is -** an error to call this function if pPager is opened on an in-memory -** database. +** If it can be used, then the value returned is the size of the journal +** file when it contains rollback data for exactly one page. ** -** If the optimization cannot be used, 0 is returned. If it can be used, -** then the value returned is the size of the journal file when it -** contains rollback data for exactly one page. +** The atomic-batch-write optimization can be used if OsDeviceCharacteristics() +** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is +** returned in this case. +** +** If neither optimization can be used, 0 is returned. */ -#ifdef SQLITE_ENABLE_ATOMIC_WRITE static int jrnlBufferSize(Pager *pPager){ assert( !MEMDB ); - if( !pPager->tempFile ){ - int dc; /* Device characteristics */ - int nSector; /* Sector size */ - int szPage; /* Page size */ - assert( isOpen(pPager->fd) ); - dc = sqlite3OsDeviceCharacteristics(pPager->fd); - nSector = pPager->sectorSize; - szPage = pPager->pageSize; +#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ + || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + int dc; /* Device characteristics */ + + assert( isOpen(pPager->fd) ); + dc = sqlite3OsDeviceCharacteristics(pPager->fd); +#else + UNUSED_PARAMETER(pPager); +#endif + +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){ + return -1; + } +#endif + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + { + int nSector = pPager->sectorSize; + int szPage = pPager->pageSize; assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); @@ -48122,11 +48710,11 @@ static int jrnlBufferSize(Pager *pPager){ } return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); -} -#else -# define jrnlBufferSize(x) 0 #endif + return 0; +} + /* ** If SQLITE_CHECK_PAGES is defined then we do some sanity checking ** on the cache using a hash function. This is used for testing @@ -48208,6 +48796,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ || szJ<16 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) || len>=nMaster + || len>szJ-16 || len==0 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) @@ -48929,7 +49518,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ } releaseAllSavepoints(pPager); - assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); + assert( isOpen(pPager->jfd) || pPager->pInJournal==0 + || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC) + ); if( isOpen(pPager->jfd) ){ assert( !pagerUseWal(pPager) ); @@ -49697,6 +50288,7 @@ static int pager_playback(Pager *pPager, int isHot){ char *zMaster = 0; /* Name of master journal file if any */ int needPagerReset; /* True to reset page prior to first page rollback */ int nPlayback = 0; /* Total number of pages restored from journal */ + u32 savedPageSize = pPager->pageSize; /* Figure out how many records are in the journal. Abort early if ** the journal is empty. @@ -49826,6 +50418,9 @@ static int pager_playback(Pager *pPager, int isHot){ assert( 0 ); end_playback: + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1); + } /* Following a rollback, the database file should be back in its original ** state prior to the start of the transaction, so invoke the ** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the @@ -49884,7 +50479,8 @@ end_playback: /* -** Read the content for page pPg out of the database file and into +** Read the content for page pPg out of the database file (or out of +** the WAL if that is where the most recent copy if found) into ** pPg->pData. A shared lock or greater must be held on the database ** file before this function is called. ** @@ -49894,30 +50490,33 @@ end_playback: ** If an IO error occurs, then the IO error is returned to the caller. ** Otherwise, SQLITE_OK is returned. */ -static int readDbPage(PgHdr *pPg, u32 iFrame){ +static int readDbPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */ - Pgno pgno = pPg->pgno; /* Page number to read */ int rc = SQLITE_OK; /* Return code */ - int pgsz = pPager->pageSize; /* Number of bytes to read */ + +#ifndef SQLITE_OMIT_WAL + u32 iFrame = 0; /* Frame of WAL containing pgno */ assert( pPager->eState>=PAGER_READER && !MEMDB ); assert( isOpen(pPager->fd) ); -#ifndef SQLITE_OMIT_WAL + if( pagerUseWal(pPager) ){ + rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); + if( rc ) return rc; + } if( iFrame ){ - /* Try to pull the page from the write-ahead log. */ - rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData); + rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData); }else #endif { - i64 iOffset = (pgno-1)*(i64)pPager->pageSize; - rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset); + i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset); if( rc==SQLITE_IOERR_SHORT_READ ){ rc = SQLITE_OK; } } - if( pgno==1 ){ + if( pPg->pgno==1 ){ if( rc ){ /* If the read is unsuccessful, set the dbFileVers[] to something ** that will never be a valid file version. dbFileVers[] is a copy @@ -49937,13 +50536,13 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){ memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers)); } } - CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM_BKPT); + CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT); PAGER_INCR(sqlite3_pager_readdb_count); PAGER_INCR(pPager->nRead); - IOTRACE(("PGIN %p %d\n", pPager, pgno)); + IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno)); PAGERTRACE(("FETCH %d page %d hash(%08x)\n", - PAGERID(pPager), pgno, pager_pagehash(pPg))); + PAGERID(pPager), pPg->pgno, pager_pagehash(pPg))); return rc; } @@ -49994,11 +50593,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){ if( sqlite3PcachePageRefcount(pPg)==1 ){ sqlite3PcacheDrop(pPg); }else{ - u32 iFrame = 0; - rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame); - if( rc==SQLITE_OK ){ - rc = readDbPage(pPg, iFrame); - } + rc = readDbPage(pPg); if( rc==SQLITE_OK ){ pPager->xReiniter(pPg); } @@ -50170,7 +50765,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ nPage = sqlite3WalDbsize(pPager->pWal); /* If the number of pages in the database is not available from the - ** WAL sub-system, determine the page counte based on the size of + ** WAL sub-system, determine the page count based on the size of ** the database file. If the size of the database file is not an ** integer multiple of the page-size, round up the result. */ @@ -50221,23 +50816,21 @@ static int pagerOpenWalIfPresent(Pager *pPager){ if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ - Pgno nPage; /* Size of the database file */ - - rc = pagerPagecount(pPager, &nPage); - if( rc ) return rc; - if( nPage==0 ){ - rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); - if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK; - isWal = 0; - }else{ - rc = sqlite3OsAccess( - pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal - ); - } + rc = sqlite3OsAccess( + pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal + ); if( rc==SQLITE_OK ){ if( isWal ){ - testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); - rc = sqlite3PagerOpenWal(pPager, 0); + Pgno nPage; /* Size of the database file */ + + rc = pagerPagecount(pPager, &nPage); + if( rc ) return rc; + if( nPage==0 ){ + rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); + }else{ + testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); + rc = sqlite3PagerOpenWal(pPager, 0); + } }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ pPager->journalMode = PAGER_JOURNALMODE_DELETE; } @@ -50506,20 +51099,17 @@ SQLITE_PRIVATE void sqlite3PagerSetFlags( } if( pPager->noSync ){ pPager->syncFlags = 0; - pPager->ckptSyncFlags = 0; }else if( pgFlags & PAGER_FULLFSYNC ){ pPager->syncFlags = SQLITE_SYNC_FULL; - pPager->ckptSyncFlags = SQLITE_SYNC_FULL; - }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){ - pPager->syncFlags = SQLITE_SYNC_NORMAL; - pPager->ckptSyncFlags = SQLITE_SYNC_FULL; }else{ pPager->syncFlags = SQLITE_SYNC_NORMAL; - pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; } - pPager->walSyncFlags = pPager->syncFlags; + pPager->walSyncFlags = (pPager->syncFlags<<2); if( pPager->fullSync ){ - pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS; + pPager->walSyncFlags |= pPager->syncFlags; + } + if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){ + pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2); } if( pgFlags & PAGER_CACHESPILL ){ pPager->doNotSpill &= ~SPILLFLAG_OFF; @@ -51018,7 +51608,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL assert( db || pPager->pWal==0 ); - sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, + sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) ); pPager->pWal = 0; @@ -51486,6 +52076,13 @@ static int pagerStress(void *p, PgHdr *pPg){ rc = pagerWalFrames(pPager, pPg, 0, 0); } }else{ + +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + if( pPager->tempFile==0 ){ + rc = sqlite3JournalCreate(pPager->jfd); + if( rc!=SQLITE_OK ) return pager_error(pPager, rc); + } +#endif /* Sync the journal file if required. */ if( pPg->flags&PGHDR_NEED_SYNC @@ -51819,13 +52416,11 @@ act_like_temp_file: assert( pPager->extraSync==0 ); assert( pPager->syncFlags==0 ); assert( pPager->walSyncFlags==0 ); - assert( pPager->ckptSyncFlags==0 ); }else{ pPager->fullSync = 1; pPager->extraSync = 0; pPager->syncFlags = SQLITE_SYNC_NORMAL; - pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS; - pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL; + pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2); } /* pPager->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ @@ -52180,19 +52775,14 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ ** detected. The chance of an undetected change is so small that ** it can be neglected. */ - Pgno nPage = 0; char dbFileVers[sizeof(pPager->dbFileVers)]; - rc = pagerPagecount(pPager, &nPage); - if( rc ) goto failed; - - if( nPage>0 ){ - IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); - rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); - if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); + rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); + if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_IOERR_SHORT_READ ){ goto failed; } - }else{ memset(dbFileVers, 0, sizeof(dbFileVers)); } @@ -52250,7 +52840,8 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ ** nothing to rollback, so this routine is a no-op. */ static void pagerUnlockIfUnused(Pager *pPager){ - if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){ + if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){ + assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */ pagerUnlockAndRollback(pPager); } } @@ -52391,14 +52982,9 @@ static int getPageNormal( memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ - u32 iFrame = 0; /* Frame to read from WAL file */ - if( pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - } assert( pPg->pPager==pPager ); pPager->aStat[PAGER_STAT_MISS]++; - rc = readDbPage(pPg, iFrame); + rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; } @@ -52541,25 +53127,39 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ /* ** Release a page reference. ** -** If the number of references to the page drop to zero, then the -** page is added to the LRU list. When all references to all pages -** are released, a rollback occurs and the lock on the database is -** removed. +** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be +** used if we know that the page being released is not the last page. +** 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. +** +** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine +** checks the total number of outstanding pages and if the number of +** pages reaches zero it drops the database lock. */ SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){ - Pager *pPager; + TESTONLY( Pager *pPager = pPg->pPager; ) assert( pPg!=0 ); - pPager = pPg->pPager; if( pPg->flags & PGHDR_MMAP ){ + assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */ pagerReleaseMapPage(pPg); }else{ sqlite3PcacheRelease(pPg); } - pagerUnlockIfUnused(pPager); + /* Do not use this routine to release the last reference to page1 */ + assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); } SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){ if( pPg ) sqlite3PagerUnrefNotNull(pPg); } +SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){ + Pager *pPager; + assert( pPg!=0 ); + assert( pPg->pgno==1 ); + assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ + pPager = pPg->pPager; + sqlite3PcacheRelease(pPg); + pagerUnlockIfUnused(pPager); +} /* ** This function is called at the start of every write transaction. @@ -53271,6 +53871,21 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( sqlite3PcacheCleanAll(pPager->pPCache); } }else{ + /* The bBatch boolean is true if the batch-atomic-write commit method + ** should be used. No rollback journal is created if batch-atomic-write + ** is enabled. + */ + sqlite3_file *fd = pPager->fd; +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */ + && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC) + && !pPager->noSync + && sqlite3JournalIsInMemory(pPager->jfd); +#else +# define bBatch 0 +#endif + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE /* The following block updates the change-counter. Exactly how it ** does this depends on whether or not the atomic-update optimization ** was enabled at compile time, and if this transaction meets the @@ -53294,33 +53909,40 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( ** in 'direct' mode. In this case the journal file will never be ** created for this transaction. */ - #ifdef SQLITE_ENABLE_ATOMIC_WRITE - PgHdr *pPg; - assert( isOpen(pPager->jfd) - || pPager->journalMode==PAGER_JOURNALMODE_OFF - || pPager->journalMode==PAGER_JOURNALMODE_WAL - ); - if( !zMaster && isOpen(pPager->jfd) - && pPager->journalOff==jrnlBufferSize(pPager) - && pPager->dbSize>=pPager->dbOrigSize - && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) - ){ - /* Update the db file change counter via the direct-write method. The - ** following call will modify the in-memory representation of page 1 - ** to include the updated change counter and then write page 1 - ** directly to the database file. Because of the atomic-write - ** property of the host file-system, this is safe. - */ - rc = pager_incr_changecounter(pPager, 1); - }else{ - rc = sqlite3JournalCreate(pPager->jfd); - if( rc==SQLITE_OK ){ - rc = pager_incr_changecounter(pPager, 0); + if( bBatch==0 ){ + PgHdr *pPg; + assert( isOpen(pPager->jfd) + || pPager->journalMode==PAGER_JOURNALMODE_OFF + || pPager->journalMode==PAGER_JOURNALMODE_WAL + ); + if( !zMaster && isOpen(pPager->jfd) + && pPager->journalOff==jrnlBufferSize(pPager) + && pPager->dbSize>=pPager->dbOrigSize + && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) + ){ + /* Update the db file change counter via the direct-write method. The + ** following call will modify the in-memory representation of page 1 + ** to include the updated change counter and then write page 1 + ** directly to the database file. Because of the atomic-write + ** property of the host file-system, this is safe. + */ + rc = pager_incr_changecounter(pPager, 1); + }else{ + rc = sqlite3JournalCreate(pPager->jfd); + if( rc==SQLITE_OK ){ + rc = pager_incr_changecounter(pPager, 0); + } } } - #else +#else +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + if( zMaster ){ + rc = sqlite3JournalCreate(pPager->jfd); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + } +#endif rc = pager_incr_changecounter(pPager, 0); - #endif +#endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; /* Write the master journal name into the journal file. If a master @@ -53343,8 +53965,24 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( */ rc = syncJournal(pPager, 0); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; - + + if( bBatch ){ + /* The pager is now in DBMOD state. But regardless of what happens + ** next, attempting to play the journal back into the database would + ** be unsafe. Close it now to make sure that does not happen. */ + sqlite3OsClose(pPager->jfd); + rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0); + if( rc!=SQLITE_OK ) goto commit_phase_one_exit; + } rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); + if( bBatch ){ + if( rc==SQLITE_OK ){ + rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); + }else{ + sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); + } + } + if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; @@ -54245,7 +54883,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, - pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, + pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); } @@ -54402,7 +55040,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ - rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, + rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); @@ -56274,9 +56912,7 @@ static int walCheckpoint( pInfo->nBackfillAttempted = mxSafeFrame; /* Sync the WAL to disk */ - if( sync_flags ){ - rc = sqlite3OsSync(pWal->pWalFd, sync_flags); - } + rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); /* If the database may grow as a result of this checkpoint, hint ** about the eventual size of the db file to the VFS layer. @@ -56317,8 +56953,8 @@ static int walCheckpoint( i64 szDb = pWal->hdr.nPage*(i64)szPage; testcase( IS_BIG_INT(szDb) ); rc = sqlite3OsTruncate(pWal->pDbFd, szDb); - if( rc==SQLITE_OK && sync_flags ){ - rc = sqlite3OsSync(pWal->pDbFd, sync_flags); + if( rc==SQLITE_OK ){ + rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags)); } } if( rc==SQLITE_OK ){ @@ -57424,8 +58060,8 @@ static int walWriteToLog( iOffset += iFirstAmt; iAmt -= iFirstAmt; pContent = (void*)(iFirstAmt + (char*)pContent); - assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) ); - rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK); + assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 ); + rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags)); if( iAmt==0 || rc ) return rc; } rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset); @@ -57595,10 +58231,10 @@ SQLITE_PRIVATE int sqlite3WalFrames( ** an out-of-order write following a WAL restart could result in ** database corruption. See the ticket: ** - ** http://localhost:591/sqlite/info/ff5be73dee + ** https://sqlite.org/src/info/ff5be73dee */ - if( pWal->syncHeader && sync_flags ){ - rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK); + if( pWal->syncHeader ){ + rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); if( rc ) return rc; } } @@ -57673,7 +58309,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( ** sector boundary is synced; the part of the last frame that extends ** past the sector boundary is written after the sync. */ - if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){ + if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){ int bSync = 1; if( pWal->padToSectorBoundary ){ int sectorSize = sqlite3SectorSize(pWal->pWalFd); @@ -57689,7 +58325,7 @@ SQLITE_PRIVATE int sqlite3WalFrames( } if( bSync ){ assert( rc==SQLITE_OK ); - rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK); + rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags)); } } @@ -58485,10 +59121,12 @@ struct BtShared { #define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */ #define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */ #define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */ -#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */ -#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */ -#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */ -#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */ +#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */ +#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */ +#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */ +#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */ +#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */ +#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */ /* ** An instance of the following structure is used to hold information @@ -58534,6 +59172,11 @@ struct CellInfo { ** eState==FAULT: Cursor fault with skipNext as error code. */ struct BtCursor { + u8 eState; /* One of the CURSOR_XXX constants (see below) */ + u8 curFlags; /* zero or more BTCF_* flags defined below */ + u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ + u8 hints; /* As configured by CursorSetHints() */ + int nOvflAlloc; /* Allocated size of aOverflow[] array */ Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext; /* Forms a linked list of all cursors */ @@ -58542,13 +59185,8 @@ struct BtCursor { i64 nKey; /* Size of pKey, or last integer key */ void *pKey; /* Saved key that was cursor last known position */ Pgno pgnoRoot; /* The root page of this tree */ - int nOvflAlloc; /* Allocated size of aOverflow[] array */ int skipNext; /* Prev() is noop if negative. Next() is noop if positive. ** Error code if eState==CURSOR_FAULT */ - u8 curFlags; /* zero or more BTCF_* flags defined below */ - u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ - u8 eState; /* One of the CURSOR_XXX constants (see below) */ - u8 hints; /* As configured by CursorSetHints() */ /* All fields above are zeroed when the cursor is allocated. See ** sqlite3BtreeCursorZero(). Fields that follow must be manually ** initialized. */ @@ -58557,7 +59195,8 @@ struct BtCursor { u16 ix; /* Current index for apPage[iPage] */ u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */ struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */ - MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ + MemPage *pPage; /* Current page */ + MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */ }; /* @@ -59186,7 +59825,7 @@ static int hasSharedCacheTableLock( ** Return true immediately. */ if( (pBtree->sharable==0) - || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted)) + || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit)) ){ return 1; } @@ -59263,7 +59902,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ for(p=pBtree->pBt->pCursor; p; p=p->pNext){ if( p->pgnoRoot==iRoot && p->pBtree!=pBtree - && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted) + && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit) ){ return 1; } @@ -59285,7 +59924,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){ assert( sqlite3BtreeHoldsMutex(p) ); assert( eLock==READ_LOCK || eLock==WRITE_LOCK ); assert( p->db!=0 ); - assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 ); + assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 ); /* If requesting a write-lock, then the Btree must have an open write ** transaction on this file. And, obviously, for this to be so there @@ -59363,7 +60002,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){ ** obtain a read-lock using this function. The only read-lock obtained ** by a connection in read-uncommitted mode is on the sqlite_master ** table, and that lock is obtained in BtreeBeginTrans(). */ - assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK ); + assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK ); /* This function should only be called on a sharable b-tree after it ** has been determined that no other b-tree holds a conflicting lock. */ @@ -59473,7 +60112,9 @@ static void downgradeAllSharedCacheTableLocks(Btree *p){ #endif /* SQLITE_OMIT_SHARED_CACHE */ -static void releasePage(MemPage *pPage); /* Forward reference */ +static void releasePage(MemPage *pPage); /* Forward reference */ +static void releasePageOne(MemPage *pPage); /* Forward reference */ +static void releasePageNotNull(MemPage *pPage); /* Forward reference */ /* ***** This routine is used inside of assert() only **** @@ -59632,11 +60273,13 @@ static void btreeClearHasContent(BtShared *pBt){ */ static void btreeReleaseAllCursorPages(BtCursor *pCur){ int i; - for(i=0; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - pCur->apPage[i] = 0; + if( pCur->iPage>=0 ){ + for(i=0; i<pCur->iPage; i++){ + releasePageNotNull(pCur->apPage[i]); + } + releasePageNotNull(pCur->pPage); + pCur->iPage = -1; } - pCur->iPage = -1; } /* @@ -59765,7 +60408,7 @@ static int SQLITE_NOINLINE saveCursorsOnList( return rc; } }else{ - testcase( p->iPage>0 ); + testcase( p->iPage>=0 ); btreeReleaseAllCursorPages(p); } } @@ -59870,6 +60513,17 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){ } /* +** Return a pointer to a fake BtCursor object that will always answer +** false to the sqlite3BtreeCursorHasMoved() routine above. The fake +** cursor returned must not be used with any other Btree interface. +*/ +SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void){ + static u8 fakeCursor = CURSOR_VALID; + assert( offsetof(BtCursor, eState)==0 ); + return (BtCursor*)&fakeCursor; +} + +/* ** This routine restores a cursor back to its original position after it ** has been moved by some outside activity (such as a btree rebalance or ** a row having been deleted out from under the cursor). @@ -60034,7 +60688,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3PagerUnref(pDbPage); - if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap); return SQLITE_OK; } @@ -60418,8 +61072,11 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ int sz2 = 0; int sz = get2byte(&data[iFree+2]); int top = get2byte(&data[hdr+5]); + if( top>=iFree ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } if( iFree2 ){ - if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT; + assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */ sz2 = get2byte(&data[iFree2+2]); assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); @@ -60450,13 +61107,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** if PRAGMA cell_size_check=ON. */ if( pc<iCellFirst || pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( pc>=iCellFirst && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrk<iCellFirst || pc+size>usableSize ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); testcase( cbrk+size==usableSize ); @@ -60476,7 +61133,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ defragment_out: if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); @@ -60508,16 +61165,10 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ int pc = get2byte(&aData[iAddr]); int x; int usableSize = pPg->pBt->usableSize; + int size; /* Size of the free slot */ assert( pc>0 ); - do{ - int size; /* Size of the free slot */ - /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of - ** increasing offset. */ - if( pc>usableSize-4 || pc<iAddr+4 ){ - *pRc = SQLITE_CORRUPT_BKPT; - return 0; - } + while( pc<=usableSize-4 ){ /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each ** freeblock form a big-endian integer which is the size of the freeblock ** in bytes, including the 4-byte header. */ @@ -60525,8 +61176,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ if( (x = size - nByte)>=0 ){ testcase( x==4 ); testcase( x==3 ); - if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){ - *pRc = SQLITE_CORRUPT_BKPT; + if( size+pc > usableSize ){ + *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); return 0; }else if( x<4 ){ /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total @@ -60546,7 +61197,11 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ } iAddr = pc; pc = get2byte(&aData[pc]); - }while( pc ); + if( pc<iAddr+size ) break; + } + if( pc ){ + *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); + } return 0; } @@ -60593,7 +61248,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } } @@ -60660,7 +61315,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ u8 hdr; /* Page header size. 0 or 100 */ u8 nFrag = 0; /* Reduction in fragmentation */ u16 iOrigSize = iSize; /* Original value of iSize */ - u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */ + u16 x; /* Offset to cell content area */ u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ unsigned char *data = pPage->aData; /* Page content */ @@ -60670,13 +61325,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<=iLast ); - - /* Overwrite deleted information with zeros when the secure_delete - ** option is enabled */ - if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){ - memset(&data[iStart], 0, iSize); - } + assert( 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. @@ -60689,11 +61338,13 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){ if( iFreeBlk<iPtr+4 ){ if( iFreeBlk==0 ) break; - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } iPtr = iFreeBlk; } - if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT; + if( iFreeBlk>pPage->pBt->usableSize-4 ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } assert( iFreeBlk>iPtr || iFreeBlk==0 ); /* At this point: @@ -60704,9 +61355,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno); iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); - if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT; + if( iEnd > pPage->pBt->usableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); } @@ -60718,28 +61371,34 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno); nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno); data[hdr+7] -= nFrag; } - if( iStart==get2byte(&data[hdr+5]) ){ + x = get2byte(&data[hdr+5]); + if( iStart<=x ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ - if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT; + if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno); put2byte(&data[hdr+1], iFreeBlk); put2byte(&data[hdr+5], iEnd); }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; } @@ -60799,7 +61458,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){ }else{ /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is ** an error. */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; @@ -60815,6 +61474,16 @@ static int decodeFlags(MemPage *pPage, int flagByte){ ** we failed to detect any corruption. */ static int btreeInitPage(MemPage *pPage){ + int pc; /* Address of a freeblock within pPage->aData[] */ + u8 hdr; /* Offset to beginning of page header */ + u8 *data; /* Equal to pPage->aData */ + BtShared *pBt; /* The main btree structure */ + int usableSize; /* Amount of usable space on each page */ + u16 cellOffset; /* Offset from start of page to first cell pointer */ + int nFree; /* Number of unused bytes on the page */ + int top; /* First byte of the cell content area */ + int iCellFirst; /* First allowable cell or freeblock offset */ + int iCellLast; /* Last possible cell or freeblock offset */ assert( pPage->pBt!=0 ); assert( pPage->pBt->db!=0 ); @@ -60822,127 +61491,119 @@ static int btreeInitPage(MemPage *pPage){ assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); + assert( pPage->isInit==0 ); - if( !pPage->isInit ){ - int pc; /* Address of a freeblock within pPage->aData[] */ - u8 hdr; /* Offset to beginning of page header */ - u8 *data; /* Equal to pPage->aData */ - BtShared *pBt; /* The main btree structure */ - int usableSize; /* Amount of usable space on each page */ - u16 cellOffset; /* Offset from start of page to first cell pointer */ - int nFree; /* Number of unused bytes on the page */ - int top; /* First byte of the cell content area */ - int iCellFirst; /* First allowable cell or freeblock offset */ - int iCellLast; /* Last possible cell or freeblock offset */ - - pBt = pPage->pBt; - - hdr = pPage->hdrOffset; - data = pPage->aData; - /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating - ** the b-tree page type. */ - if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nOverflow = 0; - usableSize = pBt->usableSize; - pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize; - pPage->aDataEnd = &data[usableSize]; - pPage->aCellIdx = &data[cellOffset]; - pPage->aDataOfst = &data[pPage->childPtrSize]; - /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates - ** the start of the cell content area. A zero value for this integer is - ** interpreted as 65536. */ - top = get2byteNotZero(&data[hdr+5]); - /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the - ** number of cells on the page. */ - pPage->nCell = get2byte(&data[hdr+3]); - if( pPage->nCell>MX_CELL(pBt) ){ - /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_BKPT; - } - testcase( pPage->nCell==MX_CELL(pBt) ); - /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only - ** possible for a root page of a table that contains no rows) then the - ** offset to the cell content area will equal the page size minus the - ** bytes of reserved space. */ - assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB ); - - /* A malformed database page might cause us to read past the end - ** of page when parsing a cell. - ** - ** The following block of code checks early to see if a cell extends - ** past the end of a page boundary and causes SQLITE_CORRUPT to be - ** returned if it does. - */ - iCellFirst = cellOffset + 2*pPage->nCell; - iCellLast = usableSize - 4; - if( pBt->db->flags & SQLITE_CellSizeCk ){ - int i; /* Index into the cell pointer array */ - int sz; /* Size of a cell */ - - if( !pPage->leaf ) iCellLast--; - for(i=0; i<pPage->nCell; i++){ - pc = get2byteAligned(&data[cellOffset+i*2]); - testcase( pc==iCellFirst ); - testcase( pc==iCellLast ); - if( pc<iCellFirst || pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; - } - sz = pPage->xCellSize(pPage, &data[pc]); - testcase( pc+sz==usableSize ); - if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_BKPT; - } - } - if( !pPage->leaf ) iCellLast++; - } + pBt = pPage->pBt; + hdr = pPage->hdrOffset; + data = pPage->aData; + /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating + ** the b-tree page type. */ + if( decodeFlags(pPage, data[hdr]) ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); + pPage->maskPage = (u16)(pBt->pageSize - 1); + pPage->nOverflow = 0; + usableSize = pBt->usableSize; + pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize; + pPage->aDataEnd = &data[usableSize]; + pPage->aCellIdx = &data[cellOffset]; + pPage->aDataOfst = &data[pPage->childPtrSize]; + /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates + ** the start of the cell content area. A zero value for this integer is + ** interpreted as 65536. */ + top = get2byteNotZero(&data[hdr+5]); + /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the + ** number of cells on the page. */ + pPage->nCell = get2byte(&data[hdr+3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + testcase( pPage->nCell==MX_CELL(pBt) ); + /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only + ** possible for a root page of a table that contains no rows) then the + ** offset to the cell content area will equal the page size minus the + ** bytes of reserved space. */ + assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB ); + + /* A malformed database page might cause us to read past the end + ** of page when parsing a cell. + ** + ** The following block of code checks early to see if a cell extends + ** past the end of a page boundary and causes SQLITE_CORRUPT to be + ** returned if it does. + */ + iCellFirst = cellOffset + 2*pPage->nCell; + iCellLast = usableSize - 4; + if( pBt->db->flags & SQLITE_CellSizeCk ){ + int i; /* Index into the cell pointer array */ + int sz; /* Size of a cell */ - /* Compute the total free space on the page - ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the - ** start of the first freeblock on the page, or is zero if there are no - ** freeblocks. */ - pc = get2byte(&data[hdr+1]); - nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ - if( pc>0 ){ - u32 next, size; - if( pc<iCellFirst ){ - /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will - ** always be at least one cell before the first freeblock. - */ - return SQLITE_CORRUPT_BKPT; + if( !pPage->leaf ) iCellLast--; + for(i=0; i<pPage->nCell; i++){ + pc = get2byteAligned(&data[cellOffset+i*2]); + testcase( pc==iCellFirst ); + testcase( pc==iCellLast ); + if( pc<iCellFirst || pc>iCellLast ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } - while( 1 ){ - if( pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */ - } - next = get2byte(&data[pc]); - size = get2byte(&data[pc+2]); - nFree = nFree + size; - if( next<=pc+size+3 ) break; - pc = next; - } - if( next>0 ){ - return SQLITE_CORRUPT_BKPT; /* Freeblock not in ascending order */ - } - if( pc+size>(unsigned int)usableSize ){ - return SQLITE_CORRUPT_BKPT; /* Last freeblock extends past page end */ + sz = pPage->xCellSize(pPage, &data[pc]); + testcase( pc+sz==usableSize ); + if( pc+sz>usableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } } + if( !pPage->leaf ) iCellLast++; + } - /* At this point, nFree contains the sum of the offset to the start - ** of the cell-content area plus the number of free bytes within - ** the cell-content area. If this is greater than the usable-size - ** of the page, then the page must be corrupted. This check also - ** serves to verify that the offset to the start of the cell-content - ** area, according to the page header, lies within the page. - */ - if( nFree>usableSize ){ - return SQLITE_CORRUPT_BKPT; + /* Compute the total free space on the page + ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the + ** start of the first freeblock on the page, or is zero if there are no + ** freeblocks. */ + pc = get2byte(&data[hdr+1]); + nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ + if( pc>0 ){ + u32 next, size; + if( pc<iCellFirst ){ + /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will + ** always be at least one cell before the first freeblock. + */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + while( 1 ){ + if( pc>iCellLast ){ + /* Freeblock off the end of the page */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + nFree = nFree + size; + if( next<=pc+size+3 ) break; + pc = next; + } + if( next>0 ){ + /* Freeblock not in ascending order */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + if( pc+size>(unsigned int)usableSize ){ + /* Last freeblock extends past page end */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } - pPage->nFree = (u16)(nFree - iCellFirst); - pPage->isInit = 1; } + + /* At this point, nFree contains the sum of the offset to the start + ** of the cell-content area plus the number of free bytes within + ** the cell-content area. If this is greater than the usable-size + ** of the page, then the page must be corrupted. This check also + ** serves to verify that the offset to the start of the cell-content + ** area, according to the page header, lies within the page. + */ + if( nFree>usableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } + pPage->nFree = (u16)(nFree - iCellFirst); + pPage->isInit = 1; return SQLITE_OK; } @@ -60961,7 +61622,7 @@ static void zeroPage(MemPage *pPage, int flags){ assert( sqlite3PagerGetData(pPage->pDbPage) == data ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pBt->mutex) ); - if( pBt->btsFlags & BTS_SECURE_DELETE ){ + if( pBt->btsFlags & BTS_FAST_SECURE ){ memset(&data[hdr], 0, pBt->usableSize - hdr); } data[hdr] = (char)flags; @@ -61052,7 +61713,7 @@ static Pgno btreePagecount(BtShared *pBt){ } SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){ assert( sqlite3BtreeHoldsMutex(p) ); - assert( ((p->pBt->nPage)&0x8000000)==0 ); + assert( ((p->pBt->nPage)&0x80000000)==0 ); return btreePagecount(p->pBt); } @@ -61079,7 +61740,7 @@ static int getAndInitPage( int rc; DbPage *pDbPage; assert( sqlite3_mutex_held(pBt->mutex) ); - assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] ); + assert( pCur==0 || ppPage==&pCur->pPage ); assert( pCur==0 || bReadOnly==pCur->curPagerFlags ); assert( pCur==0 || pCur->iPage>0 ); @@ -61106,14 +61767,17 @@ static int getAndInitPage( /* 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_BKPT; + rc = SQLITE_CORRUPT_PGNO(pgno); releasePage(*ppPage); goto getAndInitPage_error; } return SQLITE_OK; getAndInitPage_error: - if( pCur ) pCur->iPage--; + if( pCur ){ + pCur->iPage--; + pCur->pPage = pCur->apPage[pCur->iPage]; + } testcase( pgno==0 ); assert( pgno!=0 || rc==SQLITE_CORRUPT ); return rc; @@ -61122,6 +61786,8 @@ getAndInitPage_error: /* ** Release a MemPage. This should be called once for each prior ** call to btreeGetPage. +** +** Page1 is a special case and must be released using releasePageOne(). */ static void releasePageNotNull(MemPage *pPage){ assert( pPage->aData ); @@ -61135,6 +61801,16 @@ static void releasePageNotNull(MemPage *pPage){ static void releasePage(MemPage *pPage){ if( pPage ) releasePageNotNull(pPage); } +static void releasePageOne(MemPage *pPage){ + assert( pPage!=0 ); + assert( pPage->aData ); + assert( pPage->pBt ); + assert( pPage->pDbPage!=0 ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3PagerUnrefPageOne(pPage->pDbPage); +} /* ** Get an unused page. @@ -61384,8 +62060,10 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( pBt->pCursor = 0; pBt->pPage1 = 0; if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY; -#ifdef SQLITE_SECURE_DELETE +#if defined(SQLITE_SECURE_DELETE) pBt->btsFlags |= BTS_SECURE_DELETE; +#elif defined(SQLITE_FAST_SECURE_DELETE) + pBt->btsFlags |= BTS_OVERWRITE; #endif /* EVIDENCE-OF: R-51873-39618 The page size for a database file is ** determined by the 2-byte integer located at an offset of 16 bytes from @@ -61833,19 +62511,34 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ } /* -** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1, -** then make no changes. Always return the value of the BTS_SECURE_DELETE -** setting after the change. +** Change the values for the BTS_SECURE_DELETE and BTS_OVERWRITE flags: +** +** newFlag==0 Both BTS_SECURE_DELETE and BTS_OVERWRITE are cleared +** newFlag==1 BTS_SECURE_DELETE set and BTS_OVERWRITE is cleared +** newFlag==2 BTS_SECURE_DELETE cleared and BTS_OVERWRITE is set +** newFlag==(-1) No changes +** +** This routine acts as a query if newFlag is less than zero +** +** With BTS_OVERWRITE set, deleted content is overwritten by zeros, but +** freelist leaf pages are not written back to the database. Thus in-page +** deleted content is cleared, but freelist deleted content is not. +** +** With BTS_SECURE_DELETE, operation is like BTS_OVERWRITE with the addition +** that freelist leaf pages are written back into the database, increasing +** the amount of disk I/O. */ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ int b; if( p==0 ) return 0; sqlite3BtreeEnter(p); + assert( BTS_OVERWRITE==BTS_SECURE_DELETE*2 ); + assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) ); if( newFlag>=0 ){ - p->pBt->btsFlags &= ~BTS_SECURE_DELETE; - if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE; - } - b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0; + p->pBt->btsFlags &= ~BTS_FAST_SECURE; + p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag; + } + b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE; sqlite3BtreeLeave(p); return b; } @@ -61902,7 +62595,8 @@ SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){ ** set to the value passed to this function as the second parameter, ** set it so. */ -#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS +#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS \ + && !defined(SQLITE_OMIT_WAL) static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){ sqlite3 *db; Db *pDb; @@ -61996,7 +62690,7 @@ static int lockBtree(BtShared *pBt){ }else{ setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1); if( isOpen==0 ){ - releasePage(pPage1); + releasePageOne(pPage1); return SQLITE_OK; } } @@ -62043,7 +62737,7 @@ static int lockBtree(BtShared *pBt){ ** zero and return SQLITE_OK. The caller will call this function ** again with the correct page-size. */ - releasePage(pPage1); + releasePageOne(pPage1); pBt->usableSize = usableSize; pBt->pageSize = pageSize; freeTempSpace(pBt); @@ -62051,7 +62745,7 @@ static int lockBtree(BtShared *pBt){ pageSize-usableSize); return rc; } - if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){ + if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; } @@ -62097,7 +62791,7 @@ static int lockBtree(BtShared *pBt){ return SQLITE_OK; page1_init_failed: - releasePage(pPage1); + releasePageOne(pPage1); pBt->pPage1 = 0; return rc; } @@ -62142,7 +62836,7 @@ static void unlockBtreeIfUnused(BtShared *pBt){ assert( pPage1->aData ); assert( sqlite3PagerRefcount(pBt->pPager)==1 ); pBt->pPage1 = 0; - releasePageNotNull(pPage1); + releasePageOne(pPage1); } } @@ -62394,7 +63088,7 @@ static int setChildPtrmaps(MemPage *pPage){ Pgno pgno = pPage->pgno; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - rc = btreeInitPage(pPage); + rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage); if( rc!=SQLITE_OK ) return rc; nCell = pPage->nCell; @@ -62437,7 +63131,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } put4byte(pPage->aData, iTo); }else{ @@ -62445,7 +63139,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ int nCell; int rc; - rc = btreeInitPage(pPage); + rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage); if( rc ) return rc; nCell = pPage->nCell; @@ -62456,7 +63150,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocal<info.nPayload ){ if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); @@ -62474,7 +63168,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } @@ -62994,7 +63688,6 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr if( pBtree ){ sqlite3BtreeEnter(pBtree); for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - int i; if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ rc = saveCursorPosition(p); @@ -63008,10 +63701,7 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr p->eState = CURSOR_FAULT; p->skipNext = errCode; } - for(i=0; i<=p->iPage; i++){ - releasePage(p->apPage[i]); - p->apPage[i] = 0; - } + btreeReleaseAllCursorPages(p); } sqlite3BtreeLeave(pBtree); } @@ -63068,7 +63758,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){ if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); testcase( pBt->nPage!=nPage ); pBt->nPage = nPage; - releasePage(pPage1); + releasePageOne(pPage1); } assert( countValidCursors(pBt, 1)==0 ); pBt->inTransaction = TRANS_READ; @@ -63310,10 +64000,8 @@ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ Btree *pBtree = pCur->pBtree; if( pBtree ){ - int i; BtShared *pBt = pCur->pBt; sqlite3BtreeEnter(pBtree); - sqlite3BtreeClearCursor(pCur); assert( pBt->pCursor!=0 ); if( pBt->pCursor==pCur ){ pBt->pCursor = pCur->pNext; @@ -63327,12 +64015,10 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ pPrev = pPrev->pNext; }while( ALWAYS(pPrev) ); } - for(i=0; i<=pCur->iPage; i++){ - releasePage(pCur->apPage[i]); - } + btreeReleaseAllCursorPages(pCur); unlockBtreeIfUnused(pBt); sqlite3_free(pCur->aOverflow); - /* sqlite3_free(pCur); */ + sqlite3_free(pCur->pKey); sqlite3BtreeLeave(pBtree); } return SQLITE_OK; @@ -63349,9 +64035,8 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ #ifndef NDEBUG static void assertCellInfo(BtCursor *pCur){ CellInfo info; - int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); - btreeParseCell(pCur->apPage[iPage], pCur->ix, &info); + btreeParseCell(pCur->pPage, pCur->ix, &info); assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else @@ -63359,9 +64044,8 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ #endif static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){ if( pCur->info.nSize==0 ){ - int iPage = pCur->iPage; pCur->curFlags |= BTCF_ValidNKey; - btreeParseCell(pCur->apPage[iPage],pCur->ix,&pCur->info); + btreeParseCell(pCur->pPage,pCur->ix,&pCur->info); }else{ assertCellInfo(pCur); } @@ -63559,7 +64243,7 @@ static int accessPayload( unsigned char *aPayload; int rc = SQLITE_OK; int iIdx = 0; - MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ + MemPage *pPage = pCur->pPage; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ #ifdef SQLITE_DIRECT_OVERFLOW_READ unsigned char * const pBufStart = pBuf; /* Start of original out buffer */ @@ -63582,7 +64266,7 @@ static int accessPayload( ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } /* Check if data must be read/written to/from the btree page itself. */ @@ -63729,7 +64413,8 @@ static int accessPayload( } if( rc==SQLITE_OK && amt>0 ){ - return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */ + /* Overflow chain ends prematurely */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } return rc; } @@ -63754,8 +64439,8 @@ static int accessPayload( SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); - assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); + assert( pCur->iPage>=0 && pCur->pPage ); + assert( pCur->ix<pCur->pPage->nCell ); return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } @@ -63812,18 +64497,23 @@ static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 *pAmt /* Write the number of available bytes here */ ){ - u32 amt; - assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); + int amt; + assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorOwnsBtShared(pCur) ); - assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); + assert( pCur->ix<pCur->pPage->nCell ); assert( pCur->info.nSize>0 ); - assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); - assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); - amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); - if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal; - *pAmt = amt; + assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB ); + assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB); + amt = pCur->info.nLocal; + if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){ + /* There is too little space on the page for the expected amount + ** of local content. Database must be corrupt. */ + assert( CORRUPT_DB ); + amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload)); + } + *pAmt = (u32)amt; return (void*)pCur->info.pPayload; } @@ -63868,10 +64558,11 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ } pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - pCur->aiIdx[pCur->iPage++] = pCur->ix; + pCur->aiIdx[pCur->iPage] = pCur->ix; + pCur->apPage[pCur->iPage] = pCur->pPage; pCur->ix = 0; - return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], - pCur, pCur->curPagerFlags); + pCur->iPage++; + return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags); } #ifdef SQLITE_DEBUG @@ -63905,20 +64596,23 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ ** the largest cell index. */ static void moveToParent(BtCursor *pCur){ + MemPage *pLeaf; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); - assert( pCur->apPage[pCur->iPage] ); + assert( pCur->pPage ); assertParentIndex( pCur->apPage[pCur->iPage-1], pCur->aiIdx[pCur->iPage-1], - pCur->apPage[pCur->iPage]->pgno + pCur->pPage->pgno ); testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); pCur->ix = pCur->aiIdx[pCur->iPage-1]; - releasePageNotNull(pCur->apPage[pCur->iPage--]); + pLeaf = pCur->pPage; + pCur->pPage = pCur->apPage[--pCur->iPage]; + releasePageNotNull(pLeaf); } /* @@ -63930,9 +64624,9 @@ static void moveToParent(BtCursor *pCur){ ** single child page. This can only happen with the table rooted at page 1. ** ** If the b-tree structure is empty, the cursor state is set to -** CURSOR_INVALID. Otherwise, the cursor is set to point to the first -** cell located on the root (or virtual root) page and the cursor state -** is set to CURSOR_VALID. +** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise, +** the cursor is set to point to the first cell located on the root +** (or virtual root) page and the cursor state is set to CURSOR_VALID. ** ** If this function returns successfully, it may be assumed that the ** page-header flags indicate that the [virtual] root-page is the expected @@ -63950,37 +64644,40 @@ static int moveToRoot(BtCursor *pCur){ assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); - if( pCur->eState>=CURSOR_REQUIRESEEK ){ - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - sqlite3BtreeClearCursor(pCur); - } + assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 ); + assert( pCur->pgnoRoot>0 || pCur->iPage<0 ); if( pCur->iPage>=0 ){ if( pCur->iPage ){ - do{ - assert( pCur->apPage[pCur->iPage]!=0 ); - releasePageNotNull(pCur->apPage[pCur->iPage--]); - }while( pCur->iPage); + releasePageNotNull(pCur->pPage); + while( --pCur->iPage ){ + releasePageNotNull(pCur->apPage[pCur->iPage]); + } + pCur->pPage = pCur->apPage[0]; goto skip_init; } }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; - return SQLITE_OK; + return SQLITE_EMPTY; }else{ assert( pCur->iPage==(-1) ); - rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + if( pCur->eState==CURSOR_FAULT ){ + assert( pCur->skipNext!=SQLITE_OK ); + return pCur->skipNext; + } + sqlite3BtreeClearCursor(pCur); + } + rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage, 0, pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; - return rc; + return rc; } pCur->iPage = 0; - pCur->curIntKey = pCur->apPage[0]->intKey; + pCur->curIntKey = pCur->pPage->intKey; } - pRoot = pCur->apPage[0]; + pRoot = pCur->pPage; assert( pRoot->pgno==pCur->pgnoRoot ); /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor @@ -63995,7 +64692,7 @@ static int moveToRoot(BtCursor *pCur){ ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pCur->pPage->pgno); } skip_init: @@ -64003,7 +64700,7 @@ skip_init: pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); - pRoot = pCur->apPage[0]; + pRoot = pCur->pPage; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ @@ -64014,6 +64711,7 @@ skip_init: rc = moveToChild(pCur, subpage); }else{ pCur->eState = CURSOR_INVALID; + rc = SQLITE_EMPTY; } return rc; } @@ -64032,7 +64730,7 @@ static int moveToLeftmost(BtCursor *pCur){ assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ assert( pCur->ix<pPage->nCell ); pgno = get4byte(findCell(pPage, pCur->ix)); rc = moveToChild(pCur, pgno); @@ -64057,7 +64755,7 @@ static int moveToRightmost(BtCursor *pCur){ assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + while( !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->ix = pPage->nCell; rc = moveToChild(pCur, pgno); @@ -64080,14 +64778,13 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ - if( pCur->eState==CURSOR_INVALID ){ - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); - *pRes = 1; - }else{ - assert( pCur->apPage[pCur->iPage]->nCell>0 ); - *pRes = 0; - rc = moveToLeftmost(pCur); - } + assert( pCur->pPage->nCell>0 ); + *pRes = 0; + rc = moveToLeftmost(pCur); + }else if( rc==SQLITE_EMPTY ){ + assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); + *pRes = 1; + rc = SQLITE_OK; } return rc; } @@ -64111,28 +64808,26 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ for(ii=0; ii<pCur->iPage; ii++){ assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); } - assert( pCur->ix==pCur->apPage[pCur->iPage]->nCell-1 ); - assert( pCur->apPage[pCur->iPage]->leaf ); + assert( pCur->ix==pCur->pPage->nCell-1 ); + assert( pCur->pPage->leaf ); #endif return SQLITE_OK; } rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ - if( CURSOR_INVALID==pCur->eState ){ - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); - *pRes = 1; + assert( pCur->eState==CURSOR_VALID ); + *pRes = 0; + rc = moveToRightmost(pCur); + if( rc==SQLITE_OK ){ + pCur->curFlags |= BTCF_AtLast; }else{ - assert( pCur->eState==CURSOR_VALID ); - *pRes = 0; - rc = moveToRightmost(pCur); - if( rc==SQLITE_OK ){ - pCur->curFlags |= BTCF_AtLast; - }else{ - pCur->curFlags &= ~BTCF_AtLast; - } - + pCur->curFlags &= ~BTCF_AtLast; } + }else if( rc==SQLITE_EMPTY ){ + assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); + *pRes = 1; + rc = SQLITE_OK; } return rc; } @@ -64200,16 +64895,19 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( /* 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 ase, only a little more slowely */ + ** is still obtained without this case, only a little more slowely */ if( pCur->info.nKey+1==intKey && !pCur->skipNext ){ *pRes = 0; - rc = sqlite3BtreeNext(pCur, pRes); - if( rc ) return rc; - if( *pRes==0 ){ + rc = sqlite3BtreeNext(pCur, 0); + if( rc==SQLITE_OK ){ getCellInfo(pCur); if( pCur->info.nKey==intKey ){ return SQLITE_OK; } + }else if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + }else{ + return rc; } } } @@ -64228,22 +64926,23 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( rc = moveToRoot(pCur); if( rc ){ + if( rc==SQLITE_EMPTY ){ + assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 ); + *pRes = -1; + return SQLITE_OK; + } return rc; } - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] ); - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit ); - assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 ); - if( pCur->eState==CURSOR_INVALID ){ - *pRes = -1; - assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 ); - return SQLITE_OK; - } - assert( pCur->apPage[0]->intKey==pCur->curIntKey ); + assert( pCur->pPage ); + assert( pCur->pPage->isInit ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage->nCell > 0 ); + assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey ); assert( pCur->curIntKey || pIdxKey ); for(;;){ int lwr, upr, idx, c; Pgno chldPg; - MemPage *pPage = pCur->apPage[pCur->iPage]; + MemPage *pPage = pCur->pPage; u8 *pCell; /* Pointer to current cell in pPage */ /* pPage->nCell must be greater than zero. If this is the root-page @@ -64265,7 +64964,9 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( pCell = findCellPastPtr(pPage, idx); if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ - if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; + if( pCell>=pPage->aDataEnd ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } } } getVarint(pCell, (u64*)&nCellKey); @@ -64338,7 +65039,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ testcase( nCell==2 ); /* Minimum legal index key size */ if( nCell<2 ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pPage->pgno); goto moveto_finish; } pCellKey = sqlite3Malloc( nCell+18 ); @@ -64369,7 +65070,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( *pRes = 0; rc = SQLITE_OK; pCur->ix = (u16)idx; - if( pIdxKey->errCode ) rc = SQLITE_CORRUPT; + if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT; goto moveto_finish; } if( lwr>upr ) break; @@ -64380,7 +65081,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); assert( pPage->isInit ); if( pPage->leaf ){ - assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); + assert( pCur->ix<pCur->pPage->nCell ); pCur->ix = (u16)idx; *pRes = c; rc = SQLITE_OK; @@ -64434,19 +65135,22 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ ** opcode, and it that case the cursor will always be valid and ** will always point to a leaf node. */ if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1; - if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1; + if( NEVER(pCur->pPage->leaf==0) ) return -1; - for(n=1, i=0; i<=pCur->iPage; i++){ + n = pCur->pPage->nCell; + for(i=0; i<pCur->iPage; i++){ n *= pCur->apPage[i]->nCell; } return n; } /* -** Advance the cursor to the next entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the last entry in the database before -** this routine was called, then set *pRes=1. +** Advance the cursor to the next entry in the database. +** Return value: +** +** SQLITE_OK success +** SQLITE_DONE cursor is already pointing at the last element +** otherwise some kind of error occurred ** ** The main entry point is sqlite3BtreeNext(). That routine is optimized ** for the common case of merely incrementing the cell counter BtCursor.aiIdx @@ -64454,23 +65158,19 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ ** routine is called when it is necessary to move to a different page or ** to restore the cursor. ** -** The calling function will set *pRes to 0 or 1. The initial *pRes value -** will be 1 if the cursor being stepped corresponds to an SQL index and -** if this routine could have been skipped if that SQL index had been -** a unique index. Otherwise the caller will have set *pRes to zero. -** Zero is the common case. The btree implementation is free to use the -** initial *pRes value as a hint to improve performance, but the current -** SQLite btree implementation does not. (Note that the comdb2 btree -** implementation does use this hint, however.) +** If bit 0x01 of the F argument in sqlite3BtreeNext(C,F) is 1, then the +** cursor corresponds to an SQL index and this routine could have been +** skipped if the SQL index had been a unique index. The F argument +** is a hint to the implement. SQLite btree implementation does not use +** this hint, but COMDB2 does. */ -static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ +static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){ int rc; int idx; MemPage *pPage; assert( cursorOwnsBtShared(pCur) ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - assert( *pRes==0 ); if( pCur->eState!=CURSOR_VALID ){ assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); rc = restoreCursorPosition(pCur); @@ -64478,8 +65178,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ return rc; } if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; + return SQLITE_DONE; } if( pCur->skipNext ){ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT ); @@ -64492,7 +65191,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ } } - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; idx = ++pCur->ix; assert( pPage->isInit ); @@ -64511,15 +65210,14 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ } do{ if( pCur->iPage==0 ){ - *pRes = 1; pCur->eState = CURSOR_INVALID; - return SQLITE_OK; + return SQLITE_DONE; } moveToParent(pCur); - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; }while( pCur->ix>=pPage->nCell ); if( pPage->intKey ){ - return sqlite3BtreeNext(pCur, pRes); + return sqlite3BtreeNext(pCur, 0); }else{ return SQLITE_OK; } @@ -64530,20 +65228,19 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){ return moveToLeftmost(pCur); } } -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){ MemPage *pPage; + UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */ assert( cursorOwnsBtShared(pCur) ); - assert( pRes!=0 ); - assert( *pRes==0 || *pRes==1 ); + assert( flags==0 || flags==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); - *pRes = 0; - if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes); - pPage = pCur->apPage[pCur->iPage]; + if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur); + pPage = pCur->pPage; if( (++pCur->ix)>=pPage->nCell ){ pCur->ix--; - return btreeNext(pCur, pRes); + return btreeNext(pCur); } if( pPage->leaf ){ return SQLITE_OK; @@ -64553,10 +65250,12 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ } /* -** Step the cursor to the back to the previous entry in the database. If -** successful then set *pRes=0. If the cursor -** was already pointing to the first entry in the database before -** this routine was called, then set *pRes=1. +** Step the cursor to the back to the previous entry in the database. +** Return values: +** +** SQLITE_OK success +** SQLITE_DONE the cursor is already on the first element of the table +** otherwise some kind of error occurred ** ** The main entry point is sqlite3BtreePrevious(). That routine is optimized ** for the common case of merely decrementing the cell counter BtCursor.aiIdx @@ -64564,22 +65263,17 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ ** helper routine is called when it is necessary to move to a different page ** or to restore the cursor. ** -** The calling function will set *pRes to 0 or 1. The initial *pRes value -** will be 1 if the cursor being stepped corresponds to an SQL index and -** if this routine could have been skipped if that SQL index had been -** a unique index. Otherwise the caller will have set *pRes to zero. -** Zero is the common case. The btree implementation is free to use the -** initial *pRes value as a hint to improve performance, but the current -** SQLite btree implementation does not. (Note that the comdb2 btree -** implementation does use this hint, however.) +** If bit 0x01 of the F argument to sqlite3BtreePrevious(C,F) is 1, then +** the cursor corresponds to an SQL index and this routine could have been +** skipped if the SQL index had been a unique index. The F argument is a +** hint to the implement. The native SQLite btree implementation does not +** use this hint, but COMDB2 does. */ -static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ +static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){ int rc; MemPage *pPage; assert( cursorOwnsBtShared(pCur) ); - assert( pRes!=0 ); - assert( *pRes==0 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 ); assert( pCur->info.nSize==0 ); @@ -64589,8 +65283,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ return rc; } if( CURSOR_INVALID==pCur->eState ){ - *pRes = 1; - return SQLITE_OK; + return SQLITE_DONE; } if( pCur->skipNext ){ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT ); @@ -64603,7 +65296,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ } } - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; assert( pPage->isInit ); if( !pPage->leaf ){ int idx = pCur->ix; @@ -64614,8 +65307,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ while( pCur->ix==0 ){ if( pCur->iPage==0 ){ pCur->eState = CURSOR_INVALID; - *pRes = 1; - return SQLITE_OK; + return SQLITE_DONE; } moveToParent(pCur); } @@ -64623,28 +65315,27 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){ assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); pCur->ix--; - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; if( pPage->intKey && !pPage->leaf ){ - rc = sqlite3BtreePrevious(pCur, pRes); + rc = sqlite3BtreePrevious(pCur, 0); }else{ rc = SQLITE_OK; } } return rc; } -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){ assert( cursorOwnsBtShared(pCur) ); - assert( pRes!=0 ); - assert( *pRes==0 || *pRes==1 ); + assert( flags==0 || flags==1 ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); - *pRes = 0; + UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */ pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey); pCur->info.nSize = 0; if( pCur->eState!=CURSOR_VALID || pCur->ix==0 - || pCur->apPage[pCur->iPage]->leaf==0 + || pCur->pPage->leaf==0 ){ - return btreePrevious(pCur, pRes); + return btreePrevious(pCur); } pCur->ix--; return SQLITE_OK; @@ -64752,7 +65443,7 @@ static int allocateBtreePage( } testcase( iTrunk==mxPage ); if( iTrunk>mxPage || nSearch++ > n ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1); }else{ rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); } @@ -64781,7 +65472,7 @@ static int allocateBtreePage( TRACE(("ALLOCATE: %d trunk - %d 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_BKPT; + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList @@ -64815,7 +65506,7 @@ static int allocateBtreePage( MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); if( iNewTrunk>mxPage ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iNewTrunk==mxPage ); @@ -64880,7 +65571,7 @@ static int allocateBtreePage( iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); if( iPage>mxPage ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iPage==mxPage ); @@ -65138,7 +65829,7 @@ static int clearCell( unsigned char *pCell, /* First byte of the Cell */ CellInfo *pInfo /* Size information about the cell */ ){ - BtShared *pBt = pPage->pBt; + BtShared *pBt; Pgno ovflPgno; int rc; int nOvfl; @@ -65150,9 +65841,11 @@ static int clearCell( return SQLITE_OK; /* No overflow pages. Return without doing anything */ } if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ - return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ + /* Cell extends past end of page */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); + pBt = pPage->pBt; assert( pBt->usableSize > 4 ); ovflPageSize = pBt->usableSize - 4; nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize; @@ -65220,21 +65913,20 @@ static int fillInCell( ){ int nPayload; const u8 *pSrc; - int nSrc, n, rc; + int nSrc, n, rc, mn; int spaceLeft; - MemPage *pOvfl = 0; - MemPage *pToRelease = 0; + MemPage *pToRelease; unsigned char *pPrior; unsigned char *pPayload; - BtShared *pBt = pPage->pBt; - Pgno pgnoOvfl = 0; + BtShared *pBt; + Pgno pgnoOvfl; int nHeader; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); /* pPage is not necessarily writeable since pCell might be auxiliary ** buffer space that is separate from the pPage buffer area */ - assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize] + assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize] || sqlite3PagerIswriteable(pPage->pDbPage) ); /* Fill in the header. */ @@ -65254,25 +65946,36 @@ static int fillInCell( } /* Fill in the payload */ + pPayload = &pCell[nHeader]; if( nPayload<=pPage->maxLocal ){ + /* This is the common case where everything fits on the btree page + ** and no overflow pages are required. */ n = nHeader + nPayload; testcase( n==3 ); testcase( n==4 ); if( n<4 ) n = 4; *pnSize = n; - spaceLeft = nPayload; - pPrior = pCell; - }else{ - int mn = pPage->minLocal; - n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); - testcase( n==pPage->maxLocal ); - testcase( n==pPage->maxLocal+1 ); - if( n > pPage->maxLocal ) n = mn; - spaceLeft = n; - *pnSize = n + nHeader + 4; - pPrior = &pCell[nHeader+n]; + assert( nSrc<=nPayload ); + testcase( nSrc<nPayload ); + memcpy(pPayload, pSrc, nSrc); + memset(pPayload+nSrc, 0, nPayload-nSrc); + return SQLITE_OK; } - pPayload = &pCell[nHeader]; + + /* If we reach this point, it means that some of the content will need + ** to spill onto overflow pages. + */ + mn = pPage->minLocal; + n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4); + testcase( n==pPage->maxLocal ); + testcase( n==pPage->maxLocal+1 ); + if( n > pPage->maxLocal ) n = mn; + spaceLeft = n; + *pnSize = n + nHeader + 4; + pPrior = &pCell[nHeader+n]; + pToRelease = 0; + pgnoOvfl = 0; + pBt = pPage->pBt; /* At this point variables should be set as follows: ** @@ -65298,8 +66001,35 @@ static int fillInCell( #endif /* Write the payload into the local Cell and any extra into overflow pages */ - while( nPayload>0 ){ + while( 1 ){ + n = nPayload; + if( n>spaceLeft ) n = spaceLeft; + + /* If pToRelease is not zero than pPayload points into the data area + ** of pToRelease. Make sure pToRelease is still writeable. */ + assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); + + /* If pPayload is part of the data area of pPage, then make sure pPage + ** is still writeable */ + assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize] + || sqlite3PagerIswriteable(pPage->pDbPage) ); + + if( nSrc>=n ){ + memcpy(pPayload, pSrc, n); + }else if( nSrc>0 ){ + n = nSrc; + memcpy(pPayload, pSrc, n); + }else{ + memset(pPayload, 0, n); + } + nPayload -= n; + if( nPayload<=0 ) break; + pPayload += n; + pSrc += n; + nSrc -= n; + spaceLeft -= n; if( spaceLeft==0 ){ + MemPage *pOvfl = 0; #ifndef SQLITE_OMIT_AUTOVACUUM Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ if( pBt->autoVacuum ){ @@ -65352,30 +66082,6 @@ static int fillInCell( pPayload = &pOvfl->aData[4]; spaceLeft = pBt->usableSize - 4; } - n = nPayload; - if( n>spaceLeft ) n = spaceLeft; - - /* If pToRelease is not zero than pPayload points into the data area - ** of pToRelease. Make sure pToRelease is still writeable. */ - assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) ); - - /* If pPayload is part of the data area of pPage, then make sure pPage - ** is still writeable */ - assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize] - || sqlite3PagerIswriteable(pPage->pDbPage) ); - - if( nSrc>0 ){ - if( n>nSrc ) n = nSrc; - assert( pSrc ); - memcpy(pPayload, pSrc, n); - }else{ - memset(pPayload, 0, n); - } - nPayload -= n; - pPayload += n; - pSrc += n; - nSrc -= n; - spaceLeft -= n; } releasePage(pToRelease); return SQLITE_OK; @@ -65407,7 +66113,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ hdr = pPage->hdrOffset; testcase( pc==get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); - if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){ + if( pc+sz > pPage->pBt->usableSize ){ *pRC = SQLITE_CORRUPT_BKPT; return; } @@ -66245,7 +66951,7 @@ static int balance_nonroot( ** In this case, temporarily copy the cell into the aOvflSpace[] ** buffer. It will be copied out again as soon as the aSpace[] buffer ** is allocated. */ - if( pBt->btsFlags & BTS_SECURE_DELETE ){ + if( pBt->btsFlags & BTS_FAST_SECURE ){ int iOff; iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData); @@ -66274,10 +66980,8 @@ static int balance_nonroot( + nMaxCells*sizeof(u16) /* b.szCell */ + pBt->pageSize; /* aSpace1 */ - /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer - ** that is more than 6 times the database page size. */ assert( szScratch<=6*(int)pBt->pageSize ); - b.apCell = sqlite3ScratchMalloc( szScratch ); + b.apCell = sqlite3StackAllocRaw(0, szScratch ); if( b.apCell==0 ){ rc = SQLITE_NOMEM_BKPT; goto balance_cleanup; @@ -66855,7 +67559,7 @@ static int balance_nonroot( ** Cleanup before returning. */ balance_cleanup: - sqlite3ScratchFree(b.apCell); + sqlite3StackFree(0, b.apCell); for(i=0; i<nOld; i++){ releasePage(apOld[i]); } @@ -66954,7 +67658,7 @@ static int balance(BtCursor *pCur){ do { int iPage = pCur->iPage; - MemPage *pPage = pCur->apPage[iPage]; + MemPage *pPage = pCur->pPage; if( iPage==0 ){ if( pPage->nOverflow ){ @@ -66970,7 +67674,9 @@ static int balance(BtCursor *pCur){ pCur->iPage = 1; pCur->ix = 0; pCur->aiIdx[0] = 0; - assert( pCur->apPage[1]->nOverflow ); + pCur->apPage[0] = pPage; + pCur->pPage = pCur->apPage[1]; + assert( pCur->pPage->nOverflow ); } }else{ break; @@ -67050,6 +67756,7 @@ static int balance(BtCursor *pCur){ releasePage(pPage); pCur->iPage--; assert( pCur->iPage>=0 ); + pCur->pPage = pCur->apPage[pCur->iPage]; } }while( rc==SQLITE_OK ); @@ -67181,7 +67888,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; assert( pPage->intKey || pX->nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); @@ -67268,10 +67975,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** fails. Internal data structure corruption will result otherwise. ** Also, set the cursor state to invalid. This stops saveCursorPosition() ** from trying to save the current position of the cursor. */ - pCur->apPage[pCur->iPage]->nOverflow = 0; + pCur->pPage->nOverflow = 0; pCur->eState = CURSOR_INVALID; if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){ - rc = moveToRoot(pCur); + btreeReleaseAllCursorPages(pCur); if( pCur->pKeyInfo ){ assert( pCur->pKey==0 ); pCur->pKey = sqlite3Malloc( pX->nKey ); @@ -67285,7 +67992,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( pCur->nKey = pX->nKey; } } - assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); + assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 ); end_insert: return rc; @@ -67326,13 +68033,13 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); - assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell ); + assert( pCur->ix<pCur->pPage->nCell ); assert( pCur->eState==CURSOR_VALID ); assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); iCellDepth = pCur->iPage; iCellIdx = pCur->ix; - pPage = pCur->apPage[iCellDepth]; + pPage = pCur->pPage; pCell = findCell(pPage, iCellIdx); /* If the bPreserve flag is set to true, then the cursor position must @@ -67365,8 +68072,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ ** sub-tree headed by the child page of the cell being deleted. This makes ** balancing the tree following the delete operation easier. */ if( !pPage->leaf ){ - int notUsed = 0; - rc = sqlite3BtreePrevious(pCur, ¬Used); + rc = sqlite3BtreePrevious(pCur, 0); + assert( rc!=SQLITE_DONE ); if( rc ) return rc; } @@ -67398,11 +68105,16 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ ** node. The cell from the leaf node needs to be moved to the internal ** node to replace the deleted cell. */ if( !pPage->leaf ){ - MemPage *pLeaf = pCur->apPage[pCur->iPage]; + MemPage *pLeaf = pCur->pPage; int nCell; - Pgno n = pCur->apPage[iCellDepth+1]->pgno; + Pgno n; unsigned char *pTmp; + if( iCellDepth<pCur->iPage-1 ){ + n = pCur->apPage[iCellDepth+1]->pgno; + }else{ + n = pCur->pPage->pgno; + } pCell = findCell(pLeaf, pLeaf->nCell-1); if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; nCell = pLeaf->xCellSize(pLeaf, pCell); @@ -67434,16 +68146,19 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ ** well. */ rc = balance(pCur); if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){ + releasePageNotNull(pCur->pPage); + pCur->iPage--; while( pCur->iPage>iCellDepth ){ releasePage(pCur->apPage[pCur->iPage--]); } + pCur->pPage = pCur->apPage[pCur->iPage]; rc = balance(pCur); } if( rc==SQLITE_OK ){ if( bSkipnext ){ assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); - assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB ); + assert( pPage==pCur->pPage || CORRUPT_DB ); assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); pCur->eState = CURSOR_SKIPNEXT; if( iCellIdx>=pPage->nCell ){ @@ -67455,8 +68170,10 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ }else{ rc = moveToRoot(pCur); if( bPreserve ){ + btreeReleaseAllCursorPages(pCur); pCur->eState = CURSOR_REQUIRESEEK; } + if( rc==SQLITE_EMPTY ) rc = SQLITE_OK; } } return rc; @@ -67921,11 +68638,11 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ i64 nEntry = 0; /* Value to return in *pnEntry */ int rc; /* Return code */ - if( pCur->pgnoRoot==0 ){ + rc = moveToRoot(pCur); + if( rc==SQLITE_EMPTY ){ *pnEntry = 0; return SQLITE_OK; } - rc = moveToRoot(pCur); /* Unless an error occurs, the following loop runs one iteration for each ** page in the B-Tree structure (not including overflow pages). @@ -67938,7 +68655,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ ** this page contains countable entries. Increment the entry counter ** accordingly. */ - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; if( pPage->leaf || !pPage->intKey ){ nEntry += pPage->nCell; } @@ -67961,10 +68678,10 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ return moveToRoot(pCur); } moveToParent(pCur); - }while ( pCur->ix>=pCur->apPage[pCur->iPage]->nCell ); + }while ( pCur->ix>=pCur->pPage->nCell ); pCur->ix++; - pPage = pCur->apPage[pCur->iPage]; + pPage = pCur->pPage; } /* Descend to the child node of the cell that the cursor currently @@ -68805,7 +69522,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void && pCsr->pBt->inTransaction==TRANS_WRITE ); assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) ); assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) ); - assert( pCsr->apPage[pCsr->iPage]->intKey ); + assert( pCsr->pPage->intKey ); return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1); } @@ -69728,7 +70445,7 @@ copy_finished: */ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ /* If MEM_Dyn is set then Mem.xDel!=0. - ** Mem.xDel is might not be initialized if MEM_Dyn is clear. + ** Mem.xDel might not be initialized if MEM_Dyn is clear. */ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 ); @@ -69741,9 +70458,34 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ /* Cannot be both MEM_Int and MEM_Real at the same time */ assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); - /* Cannot be both MEM_Null and some other type */ - assert( (p->flags & MEM_Null)==0 || - (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob))==0 ); + if( p->flags & MEM_Null ){ + /* Cannot be both MEM_Null and some other type */ + assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob + |MEM_RowSet|MEM_Frame|MEM_Agg|MEM_Zero))==0 ); + + /* If MEM_Null is set, then either the value is a pure NULL (the usual + ** case) or it is a pointer set using sqlite3_bind_pointer() or + ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be + ** set. + */ + if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){ + /* This is a pointer type. There may be a flag to indicate what to + ** do with the pointer. */ + assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) + + ((p->flags&MEM_Ephem)!=0 ? 1 : 0) + + ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 ); + + /* No other bits set */ + assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype + |MEM_Dyn|MEM_Ephem|MEM_Static))==0 ); + }else{ + /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn, + ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */ + } + }else{ + /* The MEM_Cleared bit is only allowed on NULLs */ + assert( (p->flags & MEM_Cleared)==0 ); + } /* The szMalloc field holds the correct memory allocation size */ assert( p->szMalloc==0 @@ -69831,7 +70573,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre assert( pMem->szMalloc==0 || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); if( n<32 ) n = 32; - if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){ + if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); bPreserve = 0; }else{ @@ -69847,7 +70589,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); } - if( bPreserve && pMem->z && ALWAYS(pMem->z!=pMem->zMalloc) ){ + if( bPreserve && pMem->z ){ + assert( pMem->z!=pMem->zMalloc ); memcpy(pMem->zMalloc, pMem->z, pMem->n); } if( (pMem->flags&MEM_Dyn)!=0 ){ @@ -69886,6 +70629,20 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ } /* +** It is already known that pMem contains an unterminated string. +** Add the zero terminator. +*/ +static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ + if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ + return SQLITE_NOMEM_BKPT; + } + pMem->z[pMem->n] = 0; + pMem->z[pMem->n+1] = 0; + pMem->flags |= MEM_Term; + return SQLITE_OK; +} + +/* ** Change pMem so that its MEM_Str or MEM_Blob value is stored in ** MEM.zMalloc, where it can be safely written. ** @@ -69897,12 +70654,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ if( ExpandBlob(pMem) ) return SQLITE_NOMEM; if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ - if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ - return SQLITE_NOMEM_BKPT; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->flags |= MEM_Term; + int rc = vdbeMemAddTerminator(pMem); + if( rc ) return rc; } } pMem->flags &= ~MEM_Ephem; @@ -69942,20 +70695,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ #endif /* -** It is already known that pMem contains an unterminated string. -** Add the zero terminator. -*/ -static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){ - if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){ - return SQLITE_NOMEM_BKPT; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n+1] = 0; - pMem->flags |= MEM_Term; - return SQLITE_OK; -} - -/* ** Make sure the given Mem is \u0000 terminated. */ SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){ @@ -70273,14 +71012,21 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ */ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){ + int rc; assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){ + rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc); + if( rc==0 ){ MemSetTypeFlag(pMem, MEM_Int); }else{ - pMem->u.r = sqlite3VdbeRealValue(pMem); - MemSetTypeFlag(pMem, MEM_Real); - sqlite3VdbeIntegerAffinity(pMem); + i64 i = pMem->u.i; + sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); + if( rc==1 && pMem->u.r==(double)i ){ + pMem->u.i = i; + MemSetTypeFlag(pMem, MEM_Int); + }else{ + MemSetTypeFlag(pMem, MEM_Real); + } } } assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 ); @@ -70406,6 +71152,27 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ } } +/* A no-op destructor */ +static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); } + +/* +** Set the value stored in *pMem should already be a NULL. +** Also store a pointer to go with it. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemSetPointer( + Mem *pMem, + void *pPtr, + const char *zPType, + void (*xDestructor)(void*) +){ + assert( pMem->flags==MEM_Null ); + pMem->u.zPType = zPType ? zPType : ""; + pMem->z = pPtr; + pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term; + pMem->eSubtype = 'p'; + pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor; +} + #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Delete any previous value and set the value stored in *pMem to val, @@ -70586,7 +71353,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( if( nByte<0 ){ assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ - nByte = sqlite3Strlen30(z); + nByte = 0x7fffffff & (int)strlen(z); if( nByte>iLimit ) nByte = iLimit+1; }else{ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} @@ -70664,12 +71431,11 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize( ){ int rc; pMem->flags = MEM_Null; - if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ + if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){ rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z); if( rc==SQLITE_OK ){ - pMem->z[amt] = 0; - pMem->z[amt+1] = 0; - pMem->flags = MEM_Blob|MEM_Term; + pMem->z[amt] = 0; /* Overrun area used when reading malformed records */ + pMem->flags = MEM_Blob; pMem->n = (int)amt; }else{ sqlite3VdbeMemRelease(pMem); @@ -70818,7 +71584,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ if( pRec ){ pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx); if( pRec->pKeyInfo ){ - assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol ); + assert( pRec->pKeyInfo->nAllField==nCol ); assert( pRec->pKeyInfo->enc==ENC(db) ); pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord))); for(i=0; i<nCol; i++){ @@ -71026,7 +71792,7 @@ static int valueFromExpr( } }else if( op==TK_UMINUS ) { /* This branch happens for multiple negative signs. Ex: -(-5) */ - if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) + if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx) && pVal!=0 ){ sqlite3VdbeMemNumerify(pVal); @@ -71183,14 +71949,13 @@ static int stat4ValueFromExpr( /* Skip over any TK_COLLATE nodes */ pExpr = sqlite3ExprSkipCollate(pExpr); + assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE ); if( !pExpr ){ pVal = valueNew(db, pAlloc); if( pVal ){ sqlite3VdbeMemSetNull((Mem*)pVal); } - }else if( pExpr->op==TK_VARIABLE - || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) - ){ + }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ Vdbe *v; int iBindVar = pExpr->iColumn; sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); @@ -71198,9 +71963,7 @@ static int stat4ValueFromExpr( pVal = valueNew(db, pAlloc); if( pVal ){ rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]); - if( rc==SQLITE_OK ){ - sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); - } + sqlite3ValueApplyAffinity(pVal, affinity, ENC(db)); pVal->db = pParse->db; } } @@ -71357,7 +72120,7 @@ SQLITE_PRIVATE int sqlite3Stat4Column( SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ if( pRec ){ int i; - int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField; + int nCol = pRec->pKeyInfo->nAllField; Mem *aMem = pRec->aMem; sqlite3 *db = aMem[0].db; for(i=0; i<nCol; i++){ @@ -71453,10 +72216,12 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ db->pVdbe = p; p->magic = VDBE_MAGIC_INIT; p->pParse = pParse; + pParse->pVdbe = p; assert( pParse->aLabel==0 ); assert( pParse->nLabel==0 ); assert( pParse->nOpAlloc==0 ); assert( pParse->szOpAlloc==0 ); + sqlite3VdbeAddOp2(p, OP_Init, 0, 1); return p; } @@ -71474,16 +72239,14 @@ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){ /* ** Remember the SQL string for a prepared statement. */ -SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ - assert( isPrepareV2==1 || isPrepareV2==0 ); +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){ if( p==0 ) return; - if( !isPrepareV2 ) p->expmask = 0; -#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) - if( !isPrepareV2 ) return; -#endif + p->prepFlags = prepFlags; + if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){ + p->expmask = 0; + } assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); - p->isPrepareV2 = (u8)isPrepareV2; } /* @@ -71505,8 +72268,10 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){ zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; - pB->isPrepareV2 = pA->isPrepareV2; pB->expmask = pA->expmask; + pB->prepFlags = pA->prepFlags; + memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); + pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++; } /* @@ -71662,6 +72427,9 @@ SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){ ** "s" character in zTypes[], the register is a string if the argument is ** not NULL, or OP_Null if the value is a null pointer. For each "i" character ** in zTypes[], the register is initialized to an integer. +** +** If the input string does not end with "X" then an OP_ResultRow instruction +** is generated for the values inserted. */ SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){ va_list ap; @@ -71671,12 +72439,15 @@ SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, for(i=0; (c = zTypes[i])!=0; i++){ if( c=='s' ){ const char *z = va_arg(ap, const char*); - sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest++, 0, z, 0); + sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest+i, 0, z, 0); + }else if( c=='i' ){ + sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest+i); }else{ - assert( c=='i' ); - sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++); + goto skip_op_resultrow; } } + sqlite3VdbeAddOp2(p, OP_ResultRow, iDest, i); +skip_op_resultrow: va_end(ap); } @@ -71904,7 +72675,8 @@ static Op *opIterNext(VdbeOpIter *p){ ** * OP_VUpdate ** * OP_VRename ** * OP_FkCounter with P2==0 (immediate foreign key constraint) -** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...) +** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine +** (for CREATE TABLE AS SELECT ...) ** ** Then check that the value of Parse.mayAbort is true if an ** ABORT may be thrown, or false otherwise. Return true if it does @@ -71932,7 +72704,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ hasAbort = 1; break; } - if( opcode==OP_CreateTable ) hasCreateTable = 1; + if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1; if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1; #ifndef SQLITE_OMIT_FOREIGN_KEY if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ @@ -72011,6 +72783,27 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ p->bIsReader = 1; break; } + case OP_Next: + case OP_NextIfOpen: + case OP_SorterNext: { + pOp->p4.xAdvance = sqlite3BtreeNext; + pOp->p4type = P4_ADVANCE; + /* The code generator never codes any of these opcodes as a jump + ** to a label. They are always coded as a jump backwards to a + ** known address */ + assert( pOp->p2>=0 ); + break; + } + case OP_Prev: + case OP_PrevIfOpen: { + pOp->p4.xAdvance = sqlite3BtreePrevious; + pOp->p4type = P4_ADVANCE; + /* The code generator never codes any of these opcodes as a jump + ** to a label. They are always coded as a jump backwards to a + ** known address */ + assert( pOp->p2>=0 ); + break; + } #ifndef SQLITE_OMIT_VIRTUALTABLE case OP_VUpdate: { if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; @@ -72022,27 +72815,25 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ assert( pOp[-1].opcode==OP_Integer ); n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; - break; + /* Fall through into the default case */ } #endif - case OP_Next: - case OP_NextIfOpen: - case OP_SorterNext: { - pOp->p4.xAdvance = sqlite3BtreeNext; - pOp->p4type = P4_ADVANCE; - break; - } - case OP_Prev: - case OP_PrevIfOpen: { - pOp->p4.xAdvance = sqlite3BtreePrevious; - pOp->p4type = P4_ADVANCE; + default: { + if( pOp->p2<0 ){ + /* The mkopcodeh.tcl script has so arranged things that the only + ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to + ** have non-negative values for P2. */ + assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ); + assert( ADDR(pOp->p2)<pParse->nLabel ); + pOp->p2 = aLabel[ADDR(pOp->p2)]; + } break; } } - if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){ - assert( ADDR(pOp->p2)<pParse->nLabel ); - pOp->p2 = aLabel[ADDR(pOp->p2)]; - } + /* The mkopcodeh.tcl script has so arranged things that the only + ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to + ** have non-negative values for P2. */ + assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0); } if( pOp==p->aOp ) break; pOp--; @@ -72300,7 +73091,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ if( aOp ){ Op *pOp; for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){ - if( pOp->p4type ) freeP4(db, pOp->p4type, pOp->p4.p); + if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p); #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS sqlite3DbFree(db, pOp->zComment); #endif @@ -72715,8 +73506,8 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ int j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); - sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField); - for(j=0; j<pKeyInfo->nField; j++){ + sqlite3XPrintf(&x, "k(%d", pKeyInfo->nKeyField); + for(j=0; j<pKeyInfo->nKeyField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; const char *zColl = pColl ? pColl->zName : ""; if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; @@ -72788,7 +73579,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ int *ai = pOp->p4.ai; int n = ai[0]; /* The first element of an INTARRAY is always the ** count of the number of elements to follow */ - for(i=1; i<n; i++){ + for(i=1; i<=n; i++){ sqlite3XPrintf(&x, ",%d", ai[i]); } zTemp[0] = '['; @@ -73553,44 +74344,24 @@ static void closeAllCursors(Vdbe *p){ } /* -** Clean up the VM after a single run. -*/ -static void Cleanup(Vdbe *p){ - sqlite3 *db = p->db; - -#ifdef SQLITE_DEBUG - /* Execute assert() statements to ensure that the Vdbe.apCsr[] and - ** Vdbe.aMem[] arrays have already been cleaned up. */ - int i; - if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 ); - if( p->aMem ){ - for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); - } -#endif - - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; - p->pResultSet = 0; -} - -/* ** Set the number of result columns that will be returned by this SQL ** statement. This is now set at compile time, rather than during ** execution of the vdbe program so that sqlite3_column_count() can ** be called on an SQL statement before sqlite3_step(). */ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ - Mem *pColName; int n; sqlite3 *db = p->db; - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); - sqlite3DbFree(db, p->aColName); + if( p->nResColumn ){ + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + sqlite3DbFree(db, p->aColName); + } n = nResColumn*COLNAME_N; p->nResColumn = (u16)nResColumn; - p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); + p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n ); if( p->aColName==0 ) return; - initMemArray(p->aColName, n, p->db, MEM_Null); + initMemArray(p->aColName, n, db, MEM_Null); } /* @@ -74240,10 +75011,10 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT); sqlite3EndBenignMalloc(); db->bBenignMalloc--; - db->errCode = rc; - }else{ - sqlite3Error(db, rc); + }else if( db->pErr ){ + sqlite3ValueSetNull(db->pErr); } + db->errCode = rc; return rc; } @@ -74280,6 +75051,10 @@ static void vdbeInvokeSqllog(Vdbe *v){ ** VDBE_MAGIC_INIT. */ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + int i; +#endif + sqlite3 *db; db = p->db; @@ -74297,8 +75072,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ if( p->pc>=0 ){ vdbeInvokeSqllog(p); sqlite3VdbeTransferError(p); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; if( p->runOnlyOnce ) p->expired = 1; }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call @@ -74306,13 +75079,21 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ ** called), set the database error in this case as well. */ sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); - sqlite3DbFree(db, p->zErrMsg); - p->zErrMsg = 0; } - /* Reclaim all memory used by the VDBE + /* Reset register contents and reclaim error message memory. */ - Cleanup(p); +#ifdef SQLITE_DEBUG + /* Execute assert() statements to ensure that the Vdbe.apCsr[] and + ** Vdbe.aMem[] arrays have already been cleaned up. */ + if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 ); + if( p->aMem ){ + for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined ); + } +#endif + sqlite3DbFree(db, p->zErrMsg); + p->zErrMsg = 0; + p->pResultSet = 0; /* Save profiling information from this VDBE run. */ @@ -74320,7 +75101,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ { FILE *out = fopen("vdbe_profile.out", "a"); if( out ){ - int i; fprintf(out, "---- "); for(i=0; i<p->nOp; i++){ fprintf(out, "%02x", p->aOp[i].opcode); @@ -74533,19 +75313,18 @@ SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ */ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){ VdbeCursor *p = *pp; - if( p->eCurType==CURTYPE_BTREE ){ - if( p->deferredMoveto ){ - int iMap; - if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ - *pp = p->pAltCursor; - *piCol = iMap - 1; - return SQLITE_OK; - } - return handleDeferredMoveto(p); - } - if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return handleMovedCursor(p); + assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO ); + if( p->deferredMoveto ){ + int iMap; + if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){ + *pp = p->pAltCursor; + *piCol = iMap - 1; + return SQLITE_OK; } + return handleDeferredMoveto(p); + } + if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ + return handleMovedCursor(p); } return SQLITE_OK; } @@ -74941,13 +75720,13 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( ){ UnpackedRecord *p; /* Unpacked record to return */ int nByte; /* Number of bytes required for *p */ - nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); + nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; assert( pKeyInfo->aSortOrder!=0 ); p->pKeyInfo = pKeyInfo; - p->nField = pKeyInfo->nField + 1; + p->nField = pKeyInfo->nKeyField + 1; return p; } @@ -74987,7 +75766,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( pMem++; if( (++u)>=p->nField ) break; } - assert( u<=pKeyInfo->nField + 1 ); + assert( u<=pKeyInfo->nKeyField + 1 ); p->nField = u; } @@ -75036,9 +75815,9 @@ static int vdbeRecordCompareDebug( idx1 = getVarint32(aKey1, szHdr1); if( szHdr1>98307 ) return SQLITE_CORRUPT; d1 = szHdr1; - assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB ); + assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); assert( pKeyInfo->aSortOrder!=0 ); - assert( pKeyInfo->nField>0 ); + assert( pKeyInfo->nKeyField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ u32 serial_type1; @@ -75100,12 +75879,12 @@ debugCompareEnd: /* ** Count the number of fields (a.k.a. columns) in the record given by ** pKey,nKey. The verify that this count is less than or equal to the -** limit given by pKeyInfo->nField + pKeyInfo->nXField. +** limit given by pKeyInfo->nAllField. ** ** If this constraint is not satisfied, it means that the high-speed ** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will ** not work correctly. If this assert() ever fires, it probably means -** that the KeyInfo.nField or KeyInfo.nXField values were computed +** that the KeyInfo.nKeyField or KeyInfo.nAllField values were computed ** incorrectly. */ static void vdbeAssertFieldCountWithinLimits( @@ -75126,7 +75905,7 @@ static void vdbeAssertFieldCountWithinLimits( idx += getVarint32(aKey+idx, notUsed); nField++; } - assert( nField <= pKeyInfo->nField+pKeyInfo->nXField ); + assert( nField <= pKeyInfo->nAllField ); } #else # define vdbeAssertFieldCountWithinLimits(A,B,C) @@ -75151,7 +75930,6 @@ static int vdbeCompareMemString( }else{ int rc; const void *v1, *v2; - int n1, n2; Mem c1; Mem c2; sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null); @@ -75159,11 +75937,13 @@ static int vdbeCompareMemString( sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem); sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem); v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc); - n1 = v1==0 ? 0 : c1.n; v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc); - n2 = v2==0 ? 0 : c2.n; - rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2); - if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM_BKPT; + if( (v1==0 || v2==0) ){ + if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT; + rc = 0; + }else{ + rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2); + } sqlite3VdbeMemRelease(&c1); sqlite3VdbeMemRelease(&c2); return rc; @@ -75430,10 +76210,10 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( } VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ - assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField + assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); assert( pPKey2->pKeyInfo->aSortOrder!=0 ); - assert( pPKey2->pKeyInfo->nField>0 ); + assert( pPKey2->pKeyInfo->nKeyField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ u32 serial_type; @@ -75766,7 +76546,7 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ ** The easiest way to enforce this limit is to consider only records with ** 13 fields or less. If the first field is an integer, the maximum legal ** header size is (12*5 + 1 + 1) bytes. */ - if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){ + if( p->pKeyInfo->nAllField<=13 ){ int flags = p->aMem[0].flags; if( p->pKeyInfo->aSortOrder[0] ){ p->r1 = 1; @@ -75949,6 +76729,13 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){ } /* +** Return the SQLITE_PREPARE flags for a Vdbe. +*/ +SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe *v){ + return v->prepFlags; +} + +/* ** Return a pointer to an sqlite3_value structure containing the value bound ** parameter iVar of VM v. Except, if the value is an SQL NULL, return ** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_* @@ -75960,6 +76747,7 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff assert( iVar>0 ); if( v ){ Mem *pMem = &v->aVar[iVar-1]; + assert( (v->db->flags & SQLITE_EnableQPSG)==0 ); if( 0==(pMem->flags & MEM_Null) ){ sqlite3_value *pRet = sqlite3ValueNew(v->db); if( pRet ){ @@ -75979,6 +76767,7 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff */ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ assert( iVar>0 ); + assert( (v->db->flags & SQLITE_EnableQPSG)==0 ); if( iVar>=32 ){ v->expmask |= 0x80000000; }else{ @@ -75986,6 +76775,28 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ } } +/* +** Cause a function to throw an error if it was call from OP_PureFunc +** rather than OP_Function. +** +** OP_PureFunc means that the function must be deterministic, and should +** throw an error if it is given inputs that would make it non-deterministic. +** This routine is invoked by date/time functions that use non-deterministic +** features such as 'now'. +*/ +SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pCtx->pVdbe==0 ) return 1; +#endif + if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){ + sqlite3_result_error(pCtx, + "non-deterministic function in index expression or CHECK constraint", + -1); + return 0; + } + return 1; +} + #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored @@ -76070,7 +76881,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); - preupdate.keyinfo.nField = pTab->nCol; + preupdate.keyinfo.nKeyField = pTab->nCol; preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; @@ -76080,8 +76891,8 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); - vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked); - vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked); + vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked); + vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked); if( preupdate.aNew ){ int i; for(i=0; i<pCsr->nField; i++){ @@ -76250,7 +77061,7 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } - assert( p->isPrepareV2 || p->expmask==0 ); + assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 ); if( p->expmask ){ p->expired = 1; } @@ -76295,6 +77106,19 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ Mem *pMem = (Mem*)pVal; return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); } +SQLITE_API void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){ + Mem *p = (Mem*)pVal; + if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == + (MEM_Null|MEM_Term|MEM_Subtype) + && zPType!=0 + && p->eSubtype=='p' + && strcmp(p->u.zPType, zPType)==0 + ){ + return (void*)p->z; + }else{ + return 0; + } +} SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } @@ -76473,6 +77297,18 @@ SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } +SQLITE_API void sqlite3_result_pointer( + sqlite3_context *pCtx, + void *pPtr, + const char *zPType, + void (*xDestructor)(void*) +){ + Mem *pOut = 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; assert( sqlite3_mutex_held(pOut->db->mutex) ); @@ -76595,7 +77431,7 @@ static int doWalCallbacks(sqlite3 *db){ sqlite3BtreeEnter(pBt); nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); sqlite3BtreeLeave(pBt); - if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ + if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); } } @@ -76705,7 +77541,7 @@ static int sqlite3Step(Vdbe *p){ if( rc!=SQLITE_ROW ) checkProfileCallback(db, p); #endif - if( rc==SQLITE_DONE ){ + if( rc==SQLITE_DONE && db->autoCommit ){ assert( p->rc==SQLITE_OK ); p->rc = doWalCallbacks(db); if( p->rc!=SQLITE_OK ){ @@ -76729,8 +77565,11 @@ end_of_step: || (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE ); assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp ); - if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ - /* If this statement was prepared using sqlite3_prepare_v2(), and an + if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 + && rc!=SQLITE_ROW + && rc!=SQLITE_DONE + ){ + /* If this statement was prepared using saved SQL and an ** error has occurred, then return the error code in p->rc to the ** caller. Set the error code in the database handle to the same value. */ @@ -76746,7 +77585,6 @@ end_of_step: */ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_OK; /* Result from sqlite3Step() */ - int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */ Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */ int cnt = 0; /* Counter to prevent infinite loop of reprepares */ sqlite3 *db; /* The database connection */ @@ -76760,32 +77598,31 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ int savedPc = v->pc; - rc2 = rc = sqlite3Reprepare(v); - if( rc!=SQLITE_OK) break; + rc = sqlite3Reprepare(v); + if( rc!=SQLITE_OK ){ + /* This case occurs after failing to recompile an sql statement. + ** The error message from the SQL compiler has already been loaded + ** into the database handle. This block copies the error message + ** from the database handle into the statement and sets the statement + ** program counter to 0 to ensure that when the statement is + ** finalized or reset the parser error message is available via + ** sqlite3_errmsg() and sqlite3_errcode(). + */ + const char *zErr = (const char *)sqlite3_value_text(db->pErr); + sqlite3DbFree(db, v->zErrMsg); + if( !db->mallocFailed ){ + v->zErrMsg = sqlite3DbStrDup(db, zErr); + v->rc = rc = sqlite3ApiExit(db, rc); + } else { + v->zErrMsg = 0; + v->rc = rc = SQLITE_NOMEM_BKPT; + } + break; + } sqlite3_reset(pStmt); if( savedPc>=0 ) v->doingRerun = 1; assert( v->expired==0 ); } - if( rc2!=SQLITE_OK ){ - /* This case occurs after failing to recompile an sql statement. - ** The error message from the SQL compiler has already been loaded - ** into the database handle. This block copies the error message - ** from the database handle into the statement and sets the statement - ** program counter to 0 to ensure that when the statement is - ** finalized or reset the parser error message is available via - ** sqlite3_errmsg() and sqlite3_errcode(). - */ - const char *zErr = (const char *)sqlite3_value_text(db->pErr); - sqlite3DbFree(db, v->zErrMsg); - if( !db->mallocFailed ){ - v->zErrMsg = sqlite3DbStrDup(db, zErr); - v->rc = rc2; - } else { - v->zErrMsg = 0; - v->rc = rc = SQLITE_NOMEM_BKPT; - } - } - rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } @@ -77369,7 +78206,7 @@ static int vdbeUnbind(Vdbe *p, int i){ ** as if there had been a schema change, on the first sqlite3_step() call ** following any change to the bindings of that parameter. */ - assert( p->isPrepareV2 || p->expmask==0 ); + assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 ); if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){ p->expired = 1; } @@ -77399,8 +78236,10 @@ static int bindText( if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } - sqlite3Error(p->db, rc); - rc = sqlite3ApiExit(p->db, rc); + if( rc ){ + sqlite3Error(p->db, rc); + rc = sqlite3ApiExit(p->db, rc); + } } sqlite3_mutex_leave(p->db->mutex); }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){ @@ -77471,6 +78310,24 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ } return rc; } +SQLITE_API int sqlite3_bind_pointer( + sqlite3_stmt *pStmt, + int i, + void *pPtr, + const char *zPTtype, + void (*xDestructor)(void*) +){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor); + sqlite3_mutex_leave(p->db->mutex); + }else if( xDestructor ){ + xDestructor(pPtr); + } + return rc; +} SQLITE_API int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, @@ -77633,11 +78490,11 @@ SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt * if( pFrom->nVar!=pTo->nVar ){ return SQLITE_ERROR; } - assert( pTo->isPrepareV2 || pTo->expmask==0 ); + assert( (pTo->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pTo->expmask==0 ); if( pTo->expmask ){ pTo->expired = 1; } - assert( pFrom->isPrepareV2 || pFrom->expmask==0 ); + assert( (pFrom->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pFrom->expmask==0 ); if( pFrom->expmask ){ pFrom->expired = 1; } @@ -77707,8 +78564,19 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ return 0; } #endif - v = pVdbe->aCounter[op]; - if( resetFlag ) pVdbe->aCounter[op] = 0; + if( op==SQLITE_STMTSTATUS_MEMUSED ){ + sqlite3 *db = pVdbe->db; + sqlite3_mutex_enter(db->mutex); + v = 0; + db->pnBytesFreed = (int*)&v; + sqlite3VdbeClearObject(db, pVdbe); + sqlite3DbFree(db, pVdbe); + db->pnBytesFreed = 0; + sqlite3_mutex_leave(db->mutex); + }else{ + v = pVdbe->aCounter[op]; + if( resetFlag ) pVdbe->aCounter[op] = 0; + } return (int)v; } @@ -77760,7 +78628,7 @@ static UnpackedRecord *vdbeUnpackRecord( pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); if( pRet ){ - memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1)); sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); } return pRet; @@ -77833,7 +78701,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa */ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){ PreUpdate *p = db->pPreUpdate; - return (p ? p->keyinfo.nField : 0); + return (p ? p->keyinfo.nKeyField : 0); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ @@ -78086,7 +78954,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( Mem *pVar; /* Value of a host parameter */ StrAccum out; /* Accumulate the output here */ #ifndef SQLITE_OMIT_UTF16 - Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */ + Mem utf8; /* Used to convert UTF16 into UTF8 for display */ #endif char zBase[100]; /* Initial working space */ @@ -78555,7 +79423,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){ return 0; } - if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){ + if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){ return MEM_Int; } return MEM_Real; @@ -78863,7 +79731,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( int iCompare = 0; /* Result of last comparison */ unsigned nVmStep = 0; /* Number of virtual machine steps */ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK - unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */ + unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */ #endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ @@ -78895,6 +79763,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec( u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; assert( 0 < db->nProgressOps ); nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); + }else{ + nProgressLimit = 0xffffffff; } #endif #ifdef SQLITE_DEBUG @@ -79072,7 +79942,7 @@ check_for_interrupt: ** If the progress callback returns non-zero, exit the virtual machine with ** a return code SQLITE_ABORT. */ - if( db->xProgress!=0 && nVmStep>=nProgressLimit ){ + if( nVmStep>=nProgressLimit && db->xProgress!=0 ){ assert( db->nProgressOps!=0 ); nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps); if( db->xProgress(db->pProgressArg) ){ @@ -79614,7 +80484,7 @@ case OP_ResultRow: { /* Run the progress counter just before returning. */ if( db->xProgress!=0 - && nVmStep>=nProgressLimit + && nVmStep>=nProgressLimit && db->xProgress(db->pProgressArg)!=0 ){ rc = SQLITE_INTERRUPT; @@ -79878,117 +80748,6 @@ case OP_CollSeq: { break; } -/* Opcode: Function0 P1 P2 P3 P4 P5 -** Synopsis: r[P3]=func(r[P2@P5]) -** -** Invoke a user function (P4 is a pointer to a FuncDef object that -** defines the function) with P5 arguments taken from register P2 and -** successors. The result of the function is stored in register P3. -** Register P3 must not be one of the function inputs. -** -** P1 is a 32-bit bitmask indicating whether or not each argument to the -** function was determined to be constant at compile time. If the first -** argument was constant then bit 0 of P1 is set. This is used to determine -** whether meta data associated with a user function argument using the -** sqlite3_set_auxdata() API may be safely retained until the next -** invocation of this opcode. -** -** See also: Function, AggStep, AggFinal -*/ -/* Opcode: Function P1 P2 P3 P4 P5 -** Synopsis: r[P3]=func(r[P2@P5]) -** -** Invoke a user function (P4 is a pointer to an sqlite3_context object that -** contains a pointer to the function to be run) with P5 arguments taken -** from register P2 and successors. The result of the function is stored -** in register P3. Register P3 must not be one of the function inputs. -** -** P1 is a 32-bit bitmask indicating whether or not each argument to the -** function was determined to be constant at compile time. If the first -** argument was constant then bit 0 of P1 is set. This is used to determine -** whether meta data associated with a user function argument using the -** sqlite3_set_auxdata() API may be safely retained until the next -** invocation of this opcode. -** -** SQL functions are initially coded as OP_Function0 with P4 pointing -** to a FuncDef object. But on first evaluation, the P4 operand is -** automatically converted into an sqlite3_context object and the operation -** changed to this OP_Function opcode. In this way, the initialization of -** the sqlite3_context object occurs only once, rather than once for each -** evaluation of the function. -** -** See also: Function0, AggStep, AggFinal -*/ -case OP_Function0: { - int n; - sqlite3_context *pCtx; - - assert( pOp->p4type==P4_FUNCDEF ); - n = pOp->p5; - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); - assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); - if( pCtx==0 ) goto no_mem; - pCtx->pOut = 0; - pCtx->pFunc = pOp->p4.pFunc; - pCtx->iOp = (int)(pOp - aOp); - pCtx->pVdbe = p; - pCtx->argc = n; - pOp->p4type = P4_FUNCCTX; - pOp->p4.pCtx = pCtx; - pOp->opcode = OP_Function; - /* Fall through into OP_Function */ -} -case OP_Function: { - int i; - sqlite3_context *pCtx; - - assert( pOp->p4type==P4_FUNCCTX ); - pCtx = pOp->p4.pCtx; - - /* If this function is inside of a trigger, the register array in aMem[] - ** might change from one evaluation to the next. The next block of code - ** checks to see if the register array has changed, and if so it - ** reinitializes the relavant parts of the sqlite3_context object */ - pOut = &aMem[pOp->p3]; - if( pCtx->pOut != pOut ){ - pCtx->pOut = pOut; - for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; - } - - memAboutToChange(p, pOut); -#ifdef SQLITE_DEBUG - for(i=0; i<pCtx->argc; i++){ - assert( memIsValid(pCtx->argv[i]) ); - REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); - } -#endif - MemSetTypeFlag(pOut, MEM_Null); - pCtx->fErrorOrAux = 0; - (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ - - /* If the function returned an error, throw an exception */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); - rc = pCtx->isError; - } - sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); - if( rc ) goto abort_due_to_error; - } - - /* Copy the result of the function into register P3 */ - if( pOut->flags & (MEM_Str|MEM_Blob) ){ - sqlite3VdbeChangeEncoding(pOut, encoding); - if( sqlite3VdbeMemTooBig(pOut) ) goto too_big; - } - - REGISTER_TRACE(pOp->p3, pOut); - UPDATE_MAX_BLOBSIZE(pOut); - break; -} - /* Opcode: BitAnd P1 P2 P3 * * ** Synopsis: r[P3]=r[P1]&r[P2] ** @@ -80354,13 +81113,23 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl); } compare_op: - switch( pOp->opcode ){ - case OP_Eq: res2 = res==0; break; - case OP_Ne: res2 = res; break; - case OP_Lt: res2 = res<0; break; - case OP_Le: res2 = res<=0; break; - case OP_Gt: res2 = res>0; break; - default: res2 = res>=0; break; + /* At this point, res is negative, zero, or positive if reg[P1] is + ** less than, equal to, or greater than reg[P3], respectively. Compute + ** the answer to this operator in res2, depending on what the comparison + ** operator actually is. The next block of code depends on the fact + ** that the 6 comparison operators are consecutive integers in this + ** order: NE, EQ, GT, LE, LT, GE */ + assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 ); + assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 ); + if( res<0 ){ /* ne, eq, gt, le, lt, ge */ + static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 }; + res2 = aLTb[pOp->opcode - OP_Ne]; + }else if( res==0 ){ + static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 }; + res2 = aEQb[pOp->opcode - OP_Ne]; + }else{ + static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 }; + res2 = aGTb[pOp->opcode - OP_Ne]; } /* Undo any changes made by applyAffinity() to the input registers. */ @@ -80372,7 +81141,6 @@ compare_op: if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; iCompare = res; - res2 = res2!=0; /* For this path res2 must be exactly 0 or 1 */ if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){ /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1 ** and prevents OP_Ne from overwriting NULL with 0. This flag @@ -80503,7 +81271,7 @@ case OP_Compare: { assert( memIsValid(&aMem[p2+idx]) ); REGISTER_TRACE(p1+idx, &aMem[p1+idx]); REGISTER_TRACE(p2+idx, &aMem[p2+idx]); - assert( i<pKeyInfo->nField ); + assert( i<pKeyInfo->nKeyField ); pColl = pKeyInfo->aColl[i]; bRev = pKeyInfo->aSortOrder[i]; iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); @@ -80776,16 +81544,16 @@ case OP_Column: { const u8 *zData; /* Part of the record being decoded */ const u8 *zHdr; /* Next unparsed byte of the header */ const u8 *zEndHdr; /* Pointer to first byte after the header */ - u32 offset; /* Offset into the data */ u64 offset64; /* 64-bit offset */ - u32 avail; /* Number of bytes of available data */ u32 t; /* A type code from the record header */ Mem *pReg; /* PseudoTable input register */ pC = p->apCsr[pOp->p1]; p2 = pOp->p2; - /* If the cursor cache is stale, bring it up-to-date */ + /* If the cursor cache is stale (meaning it is not currently point at + ** the correct row) then bring it up-to-date by doing the necessary + ** B-Tree seek. */ rc = sqlite3VdbeCursorMoveto(&pC, &p2); if( rc ) goto abort_due_to_error; @@ -80803,11 +81571,13 @@ case OP_Column: { if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ if( pC->eCurType==CURTYPE_PSEUDO ){ - assert( pC->uc.pseudoTableReg>0 ); - pReg = &aMem[pC->uc.pseudoTableReg]; + /* For the special case of as pseudo-cursor, the seekResult field + ** identifies the register that holds the record */ + assert( pC->seekResult>0 ); + pReg = &aMem[pC->seekResult]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); - pC->payloadSize = pC->szRow = avail = pReg->n; + pC->payloadSize = pC->szRow = pReg->n; pC->aRow = (u8*)pReg->z; }else{ sqlite3VdbeMemSetNull(pDest); @@ -80819,23 +81589,19 @@ case OP_Column: { assert( pCrsr ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); - pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail); - assert( avail<=65536 ); /* Maximum page size is 64KiB */ - if( pC->payloadSize <= (u32)avail ){ - pC->szRow = pC->payloadSize; - }else if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ + pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow); + assert( pC->szRow<=pC->payloadSize ); + assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */ + if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; - }else{ - pC->szRow = avail; } } pC->cacheStatus = p->cacheCtr; - pC->iHdrOffset = getVarint32(pC->aRow, offset); + pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]); pC->nHdrParsed = 0; - aOffset[0] = offset; - if( avail<offset ){ /*OPTIMIZATION-IF-FALSE*/ + if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/ /* pC->aRow does not have to hold the entire row, but it does at least ** need to cover the header of the record. If pC->aRow does not contain ** the complete header, then set it to zero, forcing the header to be @@ -80852,17 +81618,26 @@ case OP_Column: { ** 3-byte type for each of the maximum of 32768 columns plus three ** extra bytes for the header length itself. 32768*3 + 3 = 98307. */ - if( offset > 98307 || offset > pC->payloadSize ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; + if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){ + goto op_column_corrupt; } - }else if( offset>0 ){ /*OPTIMIZATION-IF-TRUE*/ - /* The following goto is an optimization. It can be omitted and - ** everything will still work. But OP_Column is measurably faster - ** by skipping the subsequent conditional, which is always true. + }else{ + /* This is an optimization. By skipping over the first few tests + ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a + ** measurable performance gain. + ** + ** This branch is taken even if aOffset[0]==0. Such a record is never + ** generated by SQLite, and could be considered corruption, but we + ** accept it for historical reasons. When aOffset[0]==0, the code this + ** branch jumps to reads past the end of the record, but never more + ** than a few bytes. Even if the record occurs at the end of the page + ** content area, the "page header" comes after the page content and so + ** this overread is harmless. Similar overreads can occur for a corrupt + ** database file. */ zData = pC->aRow; assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */ + testcase( aOffset[0]==0 ); goto op_column_read_header; } } @@ -80891,6 +81666,7 @@ case OP_Column: { offset64 = aOffset[i]; zHdr = zData + pC->iHdrOffset; zEndHdr = zData + aOffset[0]; + testcase( zHdr>=zEndHdr ); do{ if( (t = zHdr[0])<0x80 ){ zHdr++; @@ -80911,9 +81687,13 @@ case OP_Column: { if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize)) || (offset64 > pC->payloadSize) ){ - if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; + if( aOffset[0]==0 ){ + i = 0; + zHdr = zEndHdr; + }else{ + if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem); + goto op_column_corrupt; + } } pC->nHdrParsed = i; @@ -81007,6 +81787,15 @@ op_column_out: UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); break; + +op_column_corrupt: + if( aOp[0].p3>0 ){ + pOp = &aOp[aOp[0].p3-1]; + break; + }else{ + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } } /* Opcode: Affinity P1 P2 * P4 * @@ -81347,7 +82136,7 @@ case OP_Savepoint: { int isSchemaChange; iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ - isSchemaChange = (db->flags & SQLITE_InternChanges)!=0; + isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0; for(ii=0; ii<db->nDb; ii++){ rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT_ROLLBACK, @@ -81366,7 +82155,7 @@ case OP_Savepoint: { if( isSchemaChange ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); - db->flags = (db->flags | SQLITE_InternChanges); + db->mDbFlags |= DBFLAG_SchemaChange; } } @@ -81646,7 +82435,7 @@ case OP_SetCookie: { if( pOp->p2==BTREE_SCHEMA_VERSION ){ /* When the schema cookie changes, record the new cookie internally */ pDb->pSchema->schema_cookie = pOp->p3; - db->flags |= SQLITE_InternChanges; + db->mDbFlags |= DBFLAG_SchemaChange; }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ pDb->pSchema->file_format = pOp->p3; @@ -81785,7 +82574,7 @@ case OP_OpenWrite: assert( (pIn2->flags & MEM_Int)!=0 ); sqlite3VdbeMemIntegerify(pIn2); p2 = (int)pIn2->u.i; - /* The p2 value always comes from a prior OP_CreateTable opcode and + /* The p2 value always comes from a prior OP_CreateBtree opcode and ** that opcode will always set the p2 value to 2 or more or else fail. ** If there were a failure, the prepared statement would have halted ** before reaching this instruction. */ @@ -81795,7 +82584,7 @@ case OP_OpenWrite: pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->enc==ENC(db) ); assert( pKeyInfo->db==db ); - nField = pKeyInfo->nField+pKeyInfo->nXField; + nField = pKeyInfo->nAllField; }else if( pOp->p4type==P4_INT32 ){ nField = pOp->p4.i; } @@ -82006,8 +82795,13 @@ case OP_OpenPseudo: { pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; - pCx->uc.pseudoTableReg = pOp->p2; + pCx->seekResult = pOp->p2; pCx->isTable = 1; + /* Give this pseudo-cursor a fake BtCursor pointer so that pCx + ** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test + ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto() + ** which is a performance optimization */ + pCx->uc.pCursor = sqlite3BtreeFakeValidCursor(); assert( pOp->p5==0 ); break; } @@ -82267,8 +83061,15 @@ case OP_SeekGT: { /* jump, in3 */ if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); if( res<0 || (res==0 && oc==OP_SeekGT) ){ res = 0; - rc = sqlite3BtreeNext(pC->uc.pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; + rc = sqlite3BtreeNext(pC->uc.pCursor, 0); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + res = 1; + }else{ + goto abort_due_to_error; + } + } }else{ res = 0; } @@ -82276,8 +83077,15 @@ case OP_SeekGT: { /* jump, in3 */ assert( oc==OP_SeekLT || oc==OP_SeekLE ); if( res>0 || (res==0 && oc==OP_SeekLT) ){ res = 0; - rc = sqlite3BtreePrevious(pC->uc.pCursor, &res); - if( rc!=SQLITE_OK ) goto abort_due_to_error; + rc = sqlite3BtreePrevious(pC->uc.pCursor, 0); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + res = 1; + }else{ + goto abort_due_to_error; + } + } }else{ /* res might be negative because the table is empty. Check to ** see if this is the case. @@ -82785,14 +83593,9 @@ case OP_InsertInt: { if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; - if( pData->flags & MEM_Null ){ - x.pData = 0; - x.nData = 0; - }else{ - assert( pData->flags & (MEM_Blob|MEM_Str) ); - x.pData = pData->z; - x.nData = pData->n; - } + assert( pData->flags & (MEM_Blob|MEM_Str) ); + x.pData = pData->z; + x.nData = pData->n; seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); if( pData->flags & MEM_Zero ){ x.nZero = pData->u.nZero; @@ -83159,7 +83962,17 @@ case OP_NullRow: { break; } -/* Opcode: Last P1 P2 P3 * * +/* Opcode: SeekEnd P1 * * * * +** +** Position cursor P1 at the end of the btree for the purpose of +** appending a new entry onto the btree. +** +** It is assumed that the cursor is used only for appending and so +** if the cursor is valid, then the cursor must already be pointing +** at the end of the btree and so no changes are made to +** the cursor. +*/ +/* Opcode: Last P1 P2 * * * ** ** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. @@ -83170,14 +83983,8 @@ case OP_NullRow: { ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. -** -** If P3 is -1, then the cursor is positioned at the end of the btree -** for the purpose of appending a new entry onto the btree. In that -** case P2 must be 0. It is assumed that the cursor is used only for -** appending and so if the cursor is valid, then the cursor must already -** be pointing at the end of the btree and so no changes are made to -** the cursor. */ +case OP_SeekEnd: case OP_Last: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; @@ -83190,22 +83997,24 @@ case OP_Last: { /* jump */ pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); - pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG - pC->seekOp = OP_Last; + pC->seekOp = pOp->opcode; #endif - if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ - rc = sqlite3BtreeLast(pCrsr, &res); - pC->nullRow = (u8)res; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - if( rc ) goto abort_due_to_error; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - } - }else{ + if( pOp->opcode==OP_SeekEnd ){ assert( pOp->p2==0 ); + pC->seekResult = -1; + if( sqlite3BtreeCursorIsValidNN(pCrsr) ){ + break; + } + } + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; + if( rc ) goto abort_due_to_error; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; } break; } @@ -83383,12 +84192,10 @@ case OP_Rewind: { /* jump */ */ case OP_SorterNext: { /* jump */ VdbeCursor *pC; - int res; pC = p->apCsr[pOp->p1]; assert( isSorter(pC) ); - res = 0; - rc = sqlite3VdbeSorterNext(db, pC, &res); + rc = sqlite3VdbeSorterNext(db, pC); goto next_tail; case OP_PrevIfOpen: /* jump */ case OP_NextIfOpen: /* jump */ @@ -83399,12 +84206,9 @@ case OP_Next: /* jump */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p5<ArraySize(p->aCounter) ); pC = p->apCsr[pOp->p1]; - res = pOp->p3; assert( pC!=0 ); assert( pC->deferredMoveto==0 ); assert( pC->eCurType==CURTYPE_BTREE ); - assert( res==0 || (res==1 && pC->isTable==0) ); - testcase( res==1 ); assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext ); @@ -83419,21 +84223,21 @@ case OP_Next: /* jump */ || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE || pC->seekOp==OP_Last ); - rc = pOp->p4.xAdvance(pC->uc.pCursor, &res); + rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); next_tail: pC->cacheStatus = CACHE_STALE; - VdbeBranchTaken(res==0,2); - if( rc ) goto abort_due_to_error; - if( res==0 ){ + VdbeBranchTaken(rc==SQLITE_OK,2); + if( rc==SQLITE_OK ){ pC->nullRow = 0; p->aCounter[pOp->p5]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif goto jump_to_p2_and_check_for_interrupt; - }else{ - pC->nullRow = 1; } + if( rc!=SQLITE_DONE ) goto abort_due_to_error; + rc = SQLITE_OK; + pC->nullRow = 1; goto check_for_interrupt; } @@ -83544,8 +84348,8 @@ case OP_IdxDelete: { break; } -/* Opcode: Seek P1 * P3 P4 * -** Synopsis: Move P3 to P1.rowid +/* Opcode: DeferredSeek P1 * P3 P4 * +** Synopsis: Move P3 to P1.rowid if needed ** ** P1 is an open index cursor and P3 is a cursor on the corresponding ** table. This opcode does a deferred seek of the P3 table cursor @@ -83572,11 +84376,11 @@ case OP_IdxDelete: { ** ** See also: Rowid, MakeRecord. */ -case OP_Seek: -case OP_IdxRowid: { /* out2 */ - VdbeCursor *pC; /* The P1 index cursor */ - VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */ - i64 rowid; /* Rowid that P1 current points to */ +case OP_DeferredSeek: +case OP_IdxRowid: { /* out2 */ + VdbeCursor *pC; /* The P1 index cursor */ + VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */ + i64 rowid; /* Rowid that P1 current points to */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; @@ -83602,7 +84406,7 @@ case OP_IdxRowid: { /* out2 */ if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - if( pOp->opcode==OP_Seek ){ + if( pOp->opcode==OP_DeferredSeek ){ assert( pOp->p3>=0 && pOp->p3<p->nCursor ); pTabCur = p->apCsr[pOp->p3]; assert( pTabCur!=0 ); @@ -83839,50 +84643,28 @@ case OP_ResetSorter: { break; } -/* Opcode: CreateTable P1 P2 * * * -** Synopsis: r[P2]=root iDb=P1 -** -** Allocate a new table in the main database file if P1==0 or in the -** auxiliary database file if P1==1 or in an attached database if -** P1>1. Write the root page number of the new table into -** register P2 -** -** The difference between a table and an index is this: A table must -** have a 4-byte integer key and can have arbitrary data. An index -** has an arbitrary key but no data. -** -** See also: CreateIndex -*/ -/* Opcode: CreateIndex P1 P2 * * * -** Synopsis: r[P2]=root iDb=P1 -** -** Allocate a new index in the main database file if P1==0 or in the -** auxiliary database file if P1==1 or in an attached database if -** P1>1. Write the root page number of the new table into -** register P2. +/* Opcode: CreateBtree P1 P2 P3 * * +** Synopsis: r[P2]=root iDb=P1 flags=P3 ** -** See documentation on OP_CreateTable for additional information. +** Allocate a new b-tree in the main database file if P1==0 or in the +** TEMP database file if P1==1 or in an attached database if +** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table +** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table. +** The root page number of the new b-tree is stored in register P2. */ -case OP_CreateIndex: /* out2 */ -case OP_CreateTable: { /* out2 */ +case OP_CreateBtree: { /* out2 */ int pgno; - int flags; Db *pDb; pOut = out2Prerelease(p, pOp); pgno = 0; + assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); - if( pOp->opcode==OP_CreateTable ){ - /* flags = BTREE_INTKEY; */ - flags = BTREE_INTKEY; - }else{ - flags = BTREE_BLOBKEY; - } - rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3); if( rc ) goto abort_due_to_error; pOut->u.i = pgno; break; @@ -84044,7 +84826,7 @@ case OP_IntegrityCk: { nRoot = pOp->p2; aRoot = pOp->p4.ai; assert( nRoot>0 ); - assert( aRoot[nRoot]==0 ); + assert( aRoot[0]==nRoot ); assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pnErr = &aMem[pOp->p3]; assert( (pnErr->flags & MEM_Int)!=0 ); @@ -84052,7 +84834,7 @@ case OP_IntegrityCk: { pIn1 = &aMem[pOp->p1]; assert( pOp->p5<db->nDb ); assert( DbMaskTest(p->btreeMask, pOp->p5) ); - z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, + z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot, (int)pnErr->u.i+1, &nErr); sqlite3VdbeMemSetNull(pIn1); if( nErr==0 ){ @@ -84848,7 +85630,7 @@ case OP_Expire: { */ case OP_TableLock: { u8 isWriteLock = (u8)pOp->p3; - if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ + if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){ int p1 = pOp->p1; assert( p1>=0 && p1<db->nDb ); assert( DbMaskTest(p->btreeMask, p1) ); @@ -85277,8 +86059,123 @@ case OP_MaxPgcnt: { /* out2 */ } #endif +/* Opcode: Function0 P1 P2 P3 P4 P5 +** Synopsis: r[P3]=func(r[P2@P5]) +** +** Invoke a user function (P4 is a pointer to a FuncDef object that +** defines the function) with P5 arguments taken from register P2 and +** successors. The result of the function is stored in register P3. +** Register P3 must not be one of the function inputs. +** +** P1 is a 32-bit bitmask indicating whether or not each argument to the +** function was determined to be constant at compile time. If the first +** argument was constant then bit 0 of P1 is set. This is used to determine +** whether meta data associated with a user function argument using the +** sqlite3_set_auxdata() API may be safely retained until the next +** invocation of this opcode. +** +** See also: Function, AggStep, AggFinal +*/ +/* Opcode: Function P1 P2 P3 P4 P5 +** Synopsis: r[P3]=func(r[P2@P5]) +** +** Invoke a user function (P4 is a pointer to an sqlite3_context object that +** contains a pointer to the function to be run) with P5 arguments taken +** from register P2 and successors. The result of the function is stored +** in register P3. Register P3 must not be one of the function inputs. +** +** P1 is a 32-bit bitmask indicating whether or not each argument to the +** function was determined to be constant at compile time. If the first +** argument was constant then bit 0 of P1 is set. This is used to determine +** whether meta data associated with a user function argument using the +** sqlite3_set_auxdata() API may be safely retained until the next +** invocation of this opcode. +** +** SQL functions are initially coded as OP_Function0 with P4 pointing +** to a FuncDef object. But on first evaluation, the P4 operand is +** automatically converted into an sqlite3_context object and the operation +** changed to this OP_Function opcode. In this way, the initialization of +** the sqlite3_context object occurs only once, rather than once for each +** evaluation of the function. +** +** See also: Function0, AggStep, AggFinal +*/ +case OP_PureFunc0: +case OP_Function0: { + int n; + sqlite3_context *pCtx; + + assert( pOp->p4type==P4_FUNCDEF ); + n = pOp->p5; + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); + assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); + assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); + pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + if( pCtx==0 ) goto no_mem; + pCtx->pOut = 0; + pCtx->pFunc = pOp->p4.pFunc; + pCtx->iOp = (int)(pOp - aOp); + pCtx->pVdbe = p; + pCtx->argc = n; + pOp->p4type = P4_FUNCCTX; + pOp->p4.pCtx = pCtx; + assert( OP_PureFunc == OP_PureFunc0+2 ); + assert( OP_Function == OP_Function0+2 ); + pOp->opcode += 2; + /* Fall through into OP_Function */ +} +case OP_PureFunc: +case OP_Function: { + int i; + sqlite3_context *pCtx; + + assert( pOp->p4type==P4_FUNCCTX ); + pCtx = pOp->p4.pCtx; + + /* If this function is inside of a trigger, the register array in aMem[] + ** might change from one evaluation to the next. The next block of code + ** checks to see if the register array has changed, and if so it + ** reinitializes the relavant parts of the sqlite3_context object */ + pOut = &aMem[pOp->p3]; + if( pCtx->pOut != pOut ){ + pCtx->pOut = pOut; + for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; + } + + memAboutToChange(p, pOut); +#ifdef SQLITE_DEBUG + for(i=0; i<pCtx->argc; i++){ + assert( memIsValid(pCtx->argv[i]) ); + REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); + } +#endif + MemSetTypeFlag(pOut, MEM_Null); + pCtx->fErrorOrAux = 0; + (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ + + /* If the function returned an error, throw an exception */ + if( pCtx->fErrorOrAux ){ + if( pCtx->isError ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); + rc = pCtx->isError; + } + sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); + if( rc ) goto abort_due_to_error; + } -/* Opcode: Init P1 P2 * P4 * + /* Copy the result of the function into register P3 */ + if( pOut->flags & (MEM_Str|MEM_Blob) ){ + sqlite3VdbeChangeEncoding(pOut, encoding); + if( sqlite3VdbeMemTooBig(pOut) ) goto too_big; + } + + REGISTER_TRACE(pOp->p3, pOut); + UPDATE_MAX_BLOBSIZE(pOut); + break; +} + + +/* Opcode: Init P1 P2 P3 P4 * ** Synopsis: Start at P2 ** ** Programs contain a single instance of this opcode as the very first @@ -85292,6 +86189,9 @@ case OP_MaxPgcnt: { /* out2 */ ** ** Increment the value of P1 so that OP_Once opcodes will jump the ** first time they are evaluated for this run. +** +** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT +** error is encountered. */ case OP_Init: { /* jump */ char *zTrace; @@ -85356,6 +86256,7 @@ case OP_Init: { /* jump */ pOp->p1 = 0; } pOp->p1++; + p->aCounter[SQLITE_STMTSTATUS_RUN]++; goto jump_to_p2; } @@ -85565,11 +86466,12 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ v->aMem[1].u.i = 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_SeekRowid. This could + ** then back it up to the point where it does the OP_NotExists. This could ** have been down with an extra OP_Goto, but simply setting the program ** counter is faster. */ - if( v->pc>3 ){ - v->pc = 3; + if( v->pc>4 ){ + v->pc = 4; + assert( v->aOp[v->pc].opcode==OP_NotExists ); rc = sqlite3VdbeExec(v); }else{ rc = sqlite3_step(p->pStmt); @@ -85631,8 +86533,8 @@ SQLITE_API int sqlite3_blob_open( int rc = SQLITE_OK; char *zErr = 0; Table *pTab; - Parse *pParse = 0; Incrblob *pBlob = 0; + Parse sParse; #ifdef SQLITE_ENABLE_API_ARMOR if( ppBlob==0 ){ @@ -85650,37 +86552,34 @@ SQLITE_API int sqlite3_blob_open( sqlite3_mutex_enter(db->mutex); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); - if( !pBlob ) goto blob_open_out; - pParse = sqlite3StackAllocRaw(db, sizeof(*pParse)); - if( !pParse ) goto blob_open_out; - do { - memset(pParse, 0, sizeof(Parse)); - pParse->db = db; + memset(&sParse, 0, sizeof(Parse)); + if( !pBlob ) goto blob_open_out; + sParse.db = db; sqlite3DbFree(db, zErr); zErr = 0; sqlite3BtreeEnterAll(db); - pTab = sqlite3LocateTable(pParse, 0, zTable, zDb); + pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); if( pTab && IsVirtual(pTab) ){ pTab = 0; - sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable); + sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); } if( pTab && !HasRowid(pTab) ){ pTab = 0; - sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable); + sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable); } #ifndef SQLITE_OMIT_VIEW if( pTab && pTab->pSelect ){ pTab = 0; - sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable); + sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); } #endif if( !pTab ){ - if( pParse->zErrMsg ){ + if( sParse.zErrMsg ){ sqlite3DbFree(db, zErr); - zErr = pParse->zErrMsg; - pParse->zErrMsg = 0; + zErr = sParse.zErrMsg; + sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); @@ -85744,7 +86643,7 @@ SQLITE_API int sqlite3_blob_open( } } - pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse); + pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse); assert( pBlob->pStmt || db->mallocFailed ); if( pBlob->pStmt ){ @@ -85780,7 +86679,8 @@ SQLITE_API int sqlite3_blob_open( sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); - sqlite3VdbeChangeP5(v, 1); + sqlite3VdbeChangeP5(v, 1); + assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); /* Make sure a mutex is held on the table to be accessed */ @@ -85795,7 +86695,7 @@ SQLITE_API int sqlite3_blob_open( aOp[0].p1 = iDb; aOp[0].p2 = pTab->tnum; aOp[0].p3 = wrFlag; - sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); + sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); } if( db->mallocFailed==0 ){ #endif @@ -85817,10 +86717,10 @@ SQLITE_API int sqlite3_blob_open( aOp[1].p4.i = pTab->nCol+1; aOp[3].p2 = pTab->nCol; - pParse->nVar = 0; - pParse->nMem = 1; - pParse->nTab = 1; - sqlite3VdbeMakeReady(v, pParse); + sParse.nVar = 0; + sParse.nMem = 1; + sParse.nTab = 1; + sqlite3VdbeMakeReady(v, &sParse); } } @@ -85842,8 +86742,7 @@ blob_open_out: } sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); - sqlite3ParserReset(pParse); - sqlite3StackFree(db, pParse); + sqlite3ParserReset(&sParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -86829,15 +87728,15 @@ static int vdbeSorterCompareText( int n2; int res; - getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2; - getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2; - res = memcmp(v1, v2, MIN(n1, n2)); + getVarint32(&p1[1], n1); + getVarint32(&p2[1], n2); + res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2); if( res==0 ){ res = n1 - n2; } if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nField>1 ){ + if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); @@ -86906,7 +87805,7 @@ static int vdbeSorterCompareInt( } if( res==0 ){ - if( pTask->pSorter->pKeyInfo->nField>1 ){ + if( pTask->pSorter->pKeyInfo->nKeyField>1 ){ res = vdbeSorterCompareTail( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); @@ -86921,7 +87820,7 @@ static int vdbeSorterCompareInt( /* ** Initialize the temporary index cursor just opened as a sorter cursor. ** -** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField) +** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField) ** to determine the number of fields that should be compared from the ** records being sorted. However, if the value passed as argument nField ** is non-zero and the sorter is able to guarantee a stable sort, nField @@ -86974,7 +87873,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); assert( pCsr->eCurType==CURTYPE_SORTER ); - szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); + szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*); sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); @@ -86986,8 +87885,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; if( nField && nWorker==0 ){ - pKeyInfo->nXField += (pKeyInfo->nField - nField); - pKeyInfo->nField = nField; + pKeyInfo->nKeyField = nField; } pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->nTask = nWorker + 1; @@ -87015,11 +87913,9 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( mxCache = MIN(mxCache, SQLITE_MAX_PMASZ); pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache); - /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of - ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary - ** large heap allocations. - */ - if( sqlite3GlobalConfig.pScratch==0 ){ + /* Avoid large memory allocations if the application has requested + ** SQLITE_CONFIG_SMALL_MALLOC. */ + if( sqlite3GlobalConfig.bSmallMalloc==0 ){ assert( pSorter->iMemory==0 ); pSorter->nMemory = pgsz; pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz); @@ -87027,7 +87923,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( } } - if( (pKeyInfo->nField+pKeyInfo->nXField)<13 + if( pKeyInfo->nAllField<13 && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) ){ pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; @@ -87342,7 +88238,7 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pTask->pUnpacked==0 ){ pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo); if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT; - pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; + pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField; pTask->pUnpacked->errCode = 0; } return SQLITE_OK; @@ -88626,9 +89522,13 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){ } /* -** Advance to the next element in the sorter. +** Advance to the next element in the sorter. Return value: +** +** SQLITE_OK success +** SQLITE_DONE end of data +** otherwise some kind of error. */ -SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){ +SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){ VdbeSorter *pSorter; int rc; /* Return code */ @@ -88642,21 +89542,22 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, in #if SQLITE_MAX_WORKER_THREADS>0 if( pSorter->bUseThreads ){ rc = vdbePmaReaderNext(pSorter->pReader); - *pbEof = (pSorter->pReader->pFd==0); + if( rc==SQLITE_OK && pSorter->pReader->pFd==0 ) rc = SQLITE_DONE; }else #endif /*if( !pSorter->bUseThreads )*/ { + int res = 0; assert( pSorter->pMerger!=0 ); assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) ); - rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof); + rc = vdbeMergeEngineStep(pSorter->pMerger, &res); + if( rc==SQLITE_OK && res ) rc = SQLITE_DONE; } }else{ SorterRecord *pFree = pSorter->list.pList; pSorter->list.pList = pFree->u.pNext; pFree->u.pNext = 0; if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree); - *pbEof = !pSorter->list.pList; - rc = SQLITE_OK; + rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE; } return rc; } @@ -88861,7 +89762,8 @@ static int memjrnlRead( int iChunkOffset; FileChunk *pChunk; -#ifdef SQLITE_ENABLE_ATOMIC_WRITE +#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ + || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) if( (iAmt+iOfst)>p->endpoint.iOffset ){ return SQLITE_IOERR_SHORT_READ; } @@ -88980,7 +89882,8 @@ static int memjrnlWrite( ** atomic-write optimization. In this case the first 28 bytes of the ** journal file may be written as part of committing the transaction. */ assert( iOfst==p->endpoint.iOffset || iOfst==0 ); -#ifdef SQLITE_ENABLE_ATOMIC_WRITE +#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ + || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) if( iOfst==0 && p->pFirst ){ assert( p->nChunkSize>iAmt ); memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); @@ -89149,17 +90052,31 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ sqlite3JournalOpen(0, 0, pJfd, 0, -1); } -#ifdef SQLITE_ENABLE_ATOMIC_WRITE +#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ + || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) /* ** If the argument p points to a MemJournal structure that is not an ** in-memory-only journal file (i.e. is one that was opened with a +ve -** nSpill parameter), and the underlying file has not yet been created, -** create it now. +** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying +** file has not yet been created, create it now. */ -SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){ +SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *pJfd){ int rc = SQLITE_OK; - if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){ - rc = memjrnlCreateFile((MemJournal*)p); + MemJournal *p = (MemJournal*)pJfd; + if( p->pMethod==&MemJournalMethods && ( +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + p->nSpill>0 +#else + /* While this appears to not be possible without ATOMIC_WRITE, the + ** paths are complex, so it seems prudent to leave the test in as + ** a NEVER(), in case our analysis is subtly flawed. */ + NEVER(p->nSpill>0) +#endif +#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE + || (p->flags & SQLITE_OPEN_MAIN_JOURNAL) +#endif + )){ + rc = memjrnlCreateFile(p); } return rc; } @@ -89226,16 +90143,22 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ int rc; testcase( ExprHasProperty(pExpr, EP_TokenOnly) ); testcase( ExprHasProperty(pExpr, EP_Reduced) ); - rc = pWalker->xExprCallback(pWalker, pExpr); - if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ - return rc & WRC_Abort; - } - if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; - if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort; - if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; - }else if( pExpr->x.pList ){ - if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + while(1){ + rc = pWalker->xExprCallback(pWalker, pExpr); + if( rc ) return rc & WRC_Abort; + if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ + if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort; + assert( pExpr->x.pList==0 || pExpr->pRight==0 ); + if( pExpr->pRight ){ + pExpr = pExpr->pRight; + continue; + }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ + if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort; + }else if( pExpr->x.pList ){ + if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; + } + } + break; } return WRC_Continue; } @@ -89290,7 +90213,7 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ pSrc = p->pSrc; if( ALWAYS(pSrc) ){ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){ + if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){ return WRC_Abort; } if( pItem->fg.isTabFunc @@ -89310,8 +90233,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ ** ** If it is not NULL, the xSelectCallback() callback is invoked before ** the walk of the expressions and FROM clause. The xSelectCallback2() -** method, if it is not NULL, is invoked following the walk of the -** expressions and FROM clause. +** method is invoked following the walk of the expressions and FROM clause, +** but only if both xSelectCallback and xSelectCallback2 are both non-NULL +** and if the expressions and FROM clause both return WRC_Continue; ** ** Return WRC_Continue under normal conditions. Return WRC_Abort if ** there is an abort request. @@ -89321,29 +90245,22 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ */ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ int rc; - if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){ - return WRC_Continue; - } - rc = WRC_Continue; - pWalker->walkerDepth++; - while( p ){ - if( pWalker->xSelectCallback ){ - rc = pWalker->xSelectCallback(pWalker, p); - if( rc ) break; - } + if( p==0 ) return WRC_Continue; + if( pWalker->xSelectCallback==0 ) return WRC_Continue; + do{ + rc = pWalker->xSelectCallback(pWalker, p); + if( rc ) return rc & WRC_Abort; if( sqlite3WalkSelectExpr(pWalker, p) || sqlite3WalkSelectFrom(pWalker, p) ){ - pWalker->walkerDepth--; return WRC_Abort; } if( pWalker->xSelectCallback2 ){ pWalker->xSelectCallback2(pWalker, p); } p = p->pPrior; - } - pWalker->walkerDepth--; - return rc & WRC_Abort; + }while( p!=0 ); + return WRC_Continue; } /************** End of walker.c **********************************************/ @@ -89828,6 +90745,7 @@ static int lookupName( sqlite3ExprDelete(db, pExpr->pRight); pExpr->pRight = 0; pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN); + ExprSetProperty(pExpr, EP_Leaf); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); @@ -89866,7 +90784,6 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr testcase( iCol==BMS-1 ); pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol); } - ExprSetProperty(p, EP_Resolved); } return p; } @@ -89926,8 +90843,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pParse = pNC->pParse; assert( pParse==pWalker->pParse ); - if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune; - ExprSetProperty(pExpr, EP_Resolved); #ifndef NDEBUG if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ SrcList *pSrcList = pNC->pSrcList; @@ -90260,7 +91175,7 @@ static int resolveOrderByTermToExprList( ** result-set entry. */ for(i=0; i<pEList->nExpr; i++){ - if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){ + if( sqlite3ExprCompare(0, pEList->a[i].pExpr, pE, -1)<2 ){ return i+1; } } @@ -90311,12 +91226,10 @@ static int resolveCompoundOrderBy( pOrderBy = pSelect->pOrderBy; if( pOrderBy==0 ) return 0; db = pParse->db; -#if SQLITE_MAX_COLUMN if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); return 1; } -#endif for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; } @@ -90408,12 +91321,10 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( struct ExprList_item *pItem; if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; -#if SQLITE_MAX_COLUMN if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); return 1; } -#endif pEList = pSelect->pEList; assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ @@ -90494,7 +91405,7 @@ static int resolveOrderGroupBy( return 1; } for(j=0; j<pSelect->pEList->nExpr; j++){ - if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ + if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ pItem->u.x.iOrderByCol = j+1; } } @@ -90780,37 +91691,29 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( u16 savedHasAgg; Walker w; - if( pExpr==0 ) return 0; -#if SQLITE_MAX_EXPR_DEPTH>0 - { - Parse *pParse = pNC->pParse; - if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){ - return 1; - } - pParse->nHeight += pExpr->nHeight; - } -#endif + if( pExpr==0 ) return SQLITE_OK; savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg); pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg); w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.xSelectCallback2 = 0; - w.walkerDepth = 0; - w.eCode = 0; w.u.pNC = pNC; +#if SQLITE_MAX_EXPR_DEPTH>0 + w.pParse->nHeight += pExpr->nHeight; + if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){ + return SQLITE_ERROR; + } +#endif sqlite3WalkExpr(&w, pExpr); #if SQLITE_MAX_EXPR_DEPTH>0 - pNC->pParse->nHeight -= pExpr->nHeight; + w.pParse->nHeight -= pExpr->nHeight; #endif - if( pNC->nErr>0 || w.pParse->nErr>0 ){ - ExprSetProperty(pExpr, EP_Error); - } if( pNC->ncFlags & NC_HasAgg ){ ExprSetProperty(pExpr, EP_Agg); } pNC->ncFlags |= savedHasAgg; - return ExprHasProperty(pExpr, EP_Error); + return pNC->nErr>0 || w.pParse->nErr>0; } /* @@ -90851,9 +91754,9 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames( Walker w; assert( p!=0 ); - memset(&w, 0, sizeof(w)); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; + w.xSelectCallback2 = 0; w.pParse = pParse; w.u.pNC = pOuterNC; sqlite3WalkSelect(&w, p); @@ -91022,6 +91925,11 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){ ** Return the collation sequence for the expression pExpr. If ** there is no defined collating sequence, return NULL. ** +** See also: sqlite3ExprNNCollSeq() +** +** The sqlite3ExprNNCollSeq() works the same exact that it returns the +** default collation if pExpr has no defined collation. +** ** The collating sequence might be determined by a COLLATE operator ** or by the presence of a column with a defined collating sequence. ** COLLATE operators take first precedence. Left operands take @@ -91087,6 +91995,32 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, 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. +** +** See also: sqlite3ExprCollSeq() +** +** The sqlite3ExprCollSeq() routine works the same except that it +** returns NULL if there is no defined collation. +*/ +SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){ + CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr); + if( p==0 ) p = pParse->db->pDfltColl; + assert( p!=0 ); + return p; +} + +/* +** Return TRUE if the two expressions have equivalent collating sequences. +*/ +SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){ + CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1); + CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2); + return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0; +} + +/* ** pExpr is an operand of a comparison operator. aff2 is the ** type affinity of the other operand. This routine returns the ** type affinity that should be used for the comparison operator. @@ -91642,7 +92576,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( pNew->iAgg = -1; if( pToken ){ if( nExtra==0 ){ - pNew->flags |= EP_IntValue; + pNew->flags |= EP_IntValue|EP_Leaf; pNew->u.iValue = iValue; }else{ pNew->u.zToken = (char*)&pNew[1]; @@ -91673,7 +92607,7 @@ SQLITE_PRIVATE Expr *sqlite3Expr( ){ Token x; x.z = zToken; - x.n = zToken ? sqlite3Strlen30(zToken) : 0; + x.n = sqlite3Strlen30(zToken); return sqlite3ExprAlloc(db, op, &x, 0); } @@ -91923,8 +92857,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ /* The Expr.x union is never used at the same time as Expr.pRight */ assert( p->x.pList==0 || p->pRight==0 ); if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft); - sqlite3ExprDelete(db, p->pRight); - if( ExprHasProperty(p, EP_xIsSelect) ){ + if( p->pRight ){ + sqlite3ExprDeleteNN(db, p->pRight); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ sqlite3ExprListDelete(db, p->x.pList); @@ -92199,10 +93134,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags) Expr *pPriorSelectCol = 0; assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, - sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) ); + pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p)); if( pNew==0 ) return 0; - pNew->nAlloc = pNew->nExpr = p->nExpr; + pNew->nExpr = p->nExpr; pItem = pNew->a; pOldItem = p->a; for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){ @@ -92356,6 +93290,13 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ ** Add a new element to the end of an expression list. If pList is ** initially NULL, then create a new expression list. ** +** The pList argument must be either NULL or a pointer to an ExprList +** obtained from a prior call to sqlite3ExprListAppend(). 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(). +** ** If a memory allocation error occurs, the entire list is freed and ** NULL is returned. If non-NULL is returned, then it is guaranteed ** that the new entry was successfully appended. @@ -92374,19 +93315,19 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( goto no_mem; } pList->nExpr = 0; - pList->nAlloc = 1; - }else if( pList->nExpr==pList->nAlloc ){ + }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ ExprList *pNew; pNew = sqlite3DbRealloc(db, pList, - sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0])); + sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0])); if( pNew==0 ){ goto no_mem; } pList = pNew; - pList->nAlloc *= 2; } pItem = &pList->a[pList->nExpr++]; - memset(pItem, 0, sizeof(*pItem)); + assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) ); + assert( offsetof(struct ExprList_item,pExpr)==0 ); + memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName)); pItem->pExpr = pExpr; return pList; @@ -92572,17 +93513,29 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){ int i; u32 m = 0; - if( pList ){ - for(i=0; i<pList->nExpr; i++){ - Expr *pExpr = pList->a[i].pExpr; - assert( pExpr!=0 ); - m |= pExpr->flags; - } + assert( pList!=0 ); + for(i=0; i<pList->nExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + assert( pExpr!=0 ); + m |= pExpr->flags; } return m; } /* +** This is a SELECT-node callback for the expression walker that +** always "fails". By "fail" in this case, we mean set +** pWalker->eCode to zero and abort. +** +** This callback is used by multiple expression walkers. +*/ +SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){ + UNUSED_PARAMETER(NotUsed); + pWalker->eCode = 0; + return WRC_Abort; +} + +/* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The ** Walker.eCode value determines the type of "constant" we are looking @@ -92658,22 +93611,19 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ } /* Fall through */ default: - testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */ - testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */ + testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail will disallow */ + testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail will disallow */ return WRC_Continue; } } -static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ - UNUSED_PARAMETER(NotUsed); - pWalker->eCode = 0; - return WRC_Abort; -} static int exprIsConst(Expr *p, int initFlag, int iCur){ Walker w; - memset(&w, 0, sizeof(w)); w.eCode = initFlag; w.xExprCallback = exprNodeIsConstant; - w.xSelectCallback = selectNodeIsConstant; + w.xSelectCallback = sqlite3SelectWalkFail; +#ifdef SQLITE_DEBUG + w.xSelectCallback2 = sqlite3SelectWalkAssert2; +#endif w.u.iCur = iCur; sqlite3WalkExpr(&w, p); return w.eCode; @@ -92723,9 +93673,9 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){ ** it constant. */ for(i=0; i<pGroupBy->nExpr; i++){ Expr *p = pGroupBy->a[i].pExpr; - if( sqlite3ExprCompare(pExpr, p, -1)<2 ){ - CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p); - if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){ + if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){ + CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p); + if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){ return WRC_Prune; } } @@ -92761,9 +93711,9 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){ */ SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){ Walker w; - memset(&w, 0, sizeof(w)); w.eCode = 1; w.xExprCallback = exprNodeIsConstantOrGroupBy; + w.xSelectCallback = 0; w.u.pGroupBy = pGroupBy; w.pParse = pParse; sqlite3WalkExpr(&w, p); @@ -92791,10 +93741,12 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ */ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){ Walker w; - memset(&w, 0, sizeof(w)); w.eCode = 1; w.xExprCallback = sqlite3ExprWalkNoop; - w.xSelectCallback = selectNodeIsConstant; + w.xSelectCallback = sqlite3SelectWalkFail; +#ifdef SQLITE_DEBUG + w.xSelectCallback2 = sqlite3SelectWalkAssert2; +#endif sqlite3WalkExpr(&w, p); return w.eCode==0; } @@ -92864,8 +93816,8 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ case TK_BLOB: return 0; case TK_COLUMN: - assert( p->pTab!=0 ); return ExprHasProperty(p, EP_CanBeNull) || + p->pTab==0 || /* Reference to column of index on expression */ (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); default: return 1; @@ -93527,7 +94479,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect( /* Loop through each expression in <exprlist>. */ r1 = sqlite3GetTempReg(pParse); r2 = sqlite3GetTempReg(pParse); - if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2); + if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC); for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ Expr *pE2 = pItem->pExpr; int iValToIns; @@ -93955,7 +94907,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ const char *z = pExpr->u.zToken; assert( z!=0 ); c = sqlite3DecOrHexToI64(z, &value); - if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){ + if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){ #ifdef SQLITE_OMIT_FLOATING_POINT sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); #else @@ -93969,7 +94921,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ } #endif }else{ - if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } + if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; } sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); } } @@ -94129,8 +95081,9 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn( if( iTabCol==XN_EXPR ){ assert( pIdx->aColExpr ); assert( pIdx->aColExpr->nExpr>iIdxCol ); - pParse->iSelfTab = iTabCur; + pParse->iSelfTab = iTabCur + 1; sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); + pParse->iSelfTab = 0; }else{ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, iTabCol, regOut); @@ -94374,13 +95327,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) case TK_COLUMN: { int iTab = pExpr->iTable; if( iTab<0 ){ - if( pParse->ckBase>0 ){ + if( pParse->iSelfTab<0 ){ /* Generating CHECK constraints or inserting into partial index */ - return pExpr->iColumn + pParse->ckBase; + return pExpr->iColumn - pParse->iSelfTab; }else{ /* Coding an expression that is part of an index where column names ** in the index refer to the table to which the index belongs */ - iTab = pParse->iSelfTab; + iTab = pParse->iSelfTab - 1; } } return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, @@ -94717,8 +95670,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target, - (char*)pDef, P4_FUNCDEF); + sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, + constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nFarg); if( nFarg && constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); @@ -94997,7 +95950,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeAtInit( struct ExprList_item *pItem; int i; for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ - if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){ + if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){ return pItem->u.iConstExprReg; } } @@ -95123,7 +96076,9 @@ SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targ ** Generate code that pushes the value of every element of the given ** expression list into a sequence of registers beginning at target. ** -** Return the number of elements evaluated. +** Return the number of elements evaluated. The number returned will +** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF +** is defined. ** ** The SQLITE_ECEL_DUP flag prevents the arguments from being ** filled using OP_SCopy. OP_Copy must be used instead. @@ -95134,6 +96089,8 @@ SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targ ** The SQLITE_ECEL_REF flag means that expressions in the list with ** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored ** in registers at srcReg, and so the value can be copied from there. +** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0 +** are simply omitted rather than being copied from srcReg. */ SQLITE_PRIVATE int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ @@ -95552,6 +96509,41 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i sqlite3ExprDelete(db, pCopy); } +/* +** Expression pVar is guaranteed to be an SQL variable. pExpr may be any +** type of expression. +** +** If pExpr is a simple SQL value - an integer, real, string, blob +** or NULL value - then the VDBE currently being prepared is configured +** to re-prepare each time a new value is bound to variable pVar. +** +** Additionally, if pExpr is a simple SQL value and the value is the +** same as that currently bound to variable pVar, non-zero is returned. +** Otherwise, if the values are not the same or if pExpr is not a simple +** SQL value, zero is returned. +*/ +static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){ + int res = 0; + int iVar; + sqlite3_value *pL, *pR = 0; + + sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR); + if( pR ){ + iVar = pVar->iColumn; + sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); + pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB); + if( pL ){ + if( sqlite3_value_type(pL)==SQLITE_TEXT ){ + sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */ + } + res = 0==sqlite3MemCompare(pL, pR, 0); + } + sqlite3ValueFree(pR); + sqlite3ValueFree(pL); + } + + return res; +} /* ** Do a deep comparison of two expression trees. Return 0 if the two @@ -95574,12 +96566,22 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i ** this routine is used, it does not hurt to get an extra 2 - that ** just might result in some slightly slower code. But returning ** an incorrect 0 or 1 could lead to a malfunction. +** +** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in +** pParse->pReprepare can be matched against literals in pB. The +** pParse->pVdbe->expmask bitmask is updated for each variable referenced. +** If pParse is NULL (the normal case) then any TK_VARIABLE term in +** Argument pParse should normally be NULL. If it is not NULL and pA or +** pB causes a return value of 2. */ -SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ +SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ u32 combinedFlags; if( pA==0 || pB==0 ){ return pB==pA ? 0 : 2; } + if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){ + return 0; + } combinedFlags = pA->flags | pB->flags; if( combinedFlags & EP_IntValue ){ if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){ @@ -95588,10 +96590,10 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ return 2; } if( pA->op!=pB->op ){ - if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){ + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){ return 1; } - if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){ + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){ return 1; } return 2; @@ -95606,8 +96608,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ if( combinedFlags & EP_xIsSelect ) return 2; - if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; - if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; + if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; + if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ if( pA->iColumn!=pB->iColumn ) return 2; @@ -95642,7 +96644,7 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; - if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; + if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1; } return 0; } @@ -95652,7 +96654,7 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ ** are ignored. */ SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ - return sqlite3ExprCompare( + return sqlite3ExprCompare(0, sqlite3ExprSkipCollate(pA), sqlite3ExprSkipCollate(pB), iTab); @@ -95674,24 +96676,29 @@ SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ ** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has ** Expr.iTable<0 then assume a table number given by iTab. ** +** If pParse is not NULL, then the values of bound variables in pE1 are +** compared against literal values in pE2 and pParse->pVdbe->expmask is +** modified to record which bound variables are referenced. If pParse +** is NULL, then false will be returned if pE1 contains any bound variables. +** ** When in doubt, return false. Returning true might give a performance ** improvement. Returning false might cause a performance reduction, but ** it will always give the correct answer and is hence always safe. */ -SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){ - if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){ +SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){ + if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){ return 1; } if( pE2->op==TK_OR - && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) - || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) + && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab) + || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) ) ){ return 1; } if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); testcase( pX!=pE1->pLeft ); - if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; + if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1; } return 0; } @@ -95799,8 +96806,8 @@ SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ Walker w; struct SrcCount cnt; assert( pExpr->op==TK_AGG_FUNCTION ); - memset(&w, 0, sizeof(w)); w.xExprCallback = exprSrcCount; + w.xSelectCallback = 0; w.u.pSrcCount = &cnt; cnt.pSrc = pSrcList; cnt.nThis = 0; @@ -95932,7 +96939,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; i<pAggInfo->nFunc; i++, pItem++){ - if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){ + if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){ break; } } @@ -95972,10 +96979,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ - UNUSED_PARAMETER(pWalker); UNUSED_PARAMETER(pSelect); + pWalker->walkerDepth++; return WRC_Continue; } +static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){ + UNUSED_PARAMETER(pSelect); + pWalker->walkerDepth--; +} /* ** Analyze the pExpr expression looking for aggregate functions and @@ -95988,9 +96999,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ */ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; - memset(&w, 0, sizeof(w)); w.xExprCallback = analyzeAggregate; w.xSelectCallback = analyzeAggregatesInSelect; + w.xSelectCallback2 = analyzeAggregatesInSelectEnd; + w.walkerDepth = 0; w.u.pNC = pNC; assert( pNC->pSrcList!=0 ); sqlite3WalkExpr(&w, pExpr); @@ -96091,8 +97103,8 @@ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){ int i; if( pParse->nRangeReg>0 - && pParse->iRangeReg+pParse->nRangeReg<iLast - && pParse->iRangeReg>=iFirst + && pParse->iRangeReg+pParse->nRangeReg > iFirst + && pParse->iRangeReg <= iLast ){ return 0; } @@ -96484,7 +97496,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ ** Or, if zName is not a system table, zero is returned. */ static int isSystemTable(Parse *pParse, const char *zName){ - if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); return 1; } @@ -96512,9 +97524,9 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( char *zWhere = 0; /* Where clause to locate temp triggers */ #endif VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ - int savedDbFlags; /* Saved value of db->flags */ + u32 savedDbFlags; /* Saved value of db->mDbFlags */ - savedDbFlags = db->flags; + savedDbFlags = db->mDbFlags; if( NEVER(db->mallocFailed) ) goto exit_rename_table; assert( pSrc->nSrc==1 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); @@ -96523,7 +97535,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; - db->flags |= SQLITE_PreferBuiltin; + db->mDbFlags |= DBFLAG_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ zName = sqlite3NameFromToken(db, pName); @@ -96688,7 +97700,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( exit_rename_table: sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, zName); - db->flags = savedDbFlags; + db->mDbFlags = savedDbFlags; } /* @@ -96789,11 +97801,11 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); if( zCol ){ char *zEnd = &zCol[pColDef->n-1]; - int savedDbFlags = db->flags; + u32 savedDbFlags = db->mDbFlags; while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){ *zEnd-- = '\0'; } - db->flags |= SQLITE_PreferBuiltin; + db->mDbFlags |= DBFLAG_PreferBuiltin; sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " @@ -96802,7 +97814,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ zTab ); sqlite3DbFree(db, zCol); - db->flags = savedDbFlags; + db->mDbFlags = savedDbFlags; } /* Make sure the schema version is at least 3. But do not upgrade @@ -98903,7 +99915,8 @@ static void attachFunc( char *zPath = 0; char *zErr = 0; unsigned int flags; - Db *aNew; + Db *aNew; /* New array of Db pointers */ + Db *pNew; /* Db object for the newly attached database */ char *zErrDyn = 0; sqlite3_vfs *pVfs; @@ -98926,10 +99939,6 @@ static void attachFunc( ); goto attach_error; } - if( !db->autoCommit ){ - zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); - goto attach_error; - } for(i=0; i<db->nDb; i++){ char *z = db->aDb[i].zDbSName; assert( z && zName ); @@ -98951,8 +99960,8 @@ static void attachFunc( if( aNew==0 ) return; } db->aDb = aNew; - aNew = &db->aDb[db->nDb]; - memset(aNew, 0, sizeof(*aNew)); + pNew = &db->aDb[db->nDb]; + memset(pNew, 0, sizeof(*pNew)); /* Open the database file. If the btree is successfully opened, use ** it to obtain the database schema. At this point the schema may @@ -98968,7 +99977,7 @@ static void attachFunc( } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags); + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); sqlite3_free( zPath ); db->nDb++; db->skipBtreeMutex = 0; @@ -98977,28 +99986,28 @@ static void attachFunc( zErrDyn = sqlite3MPrintf(db, "database is already attached"); }else if( rc==SQLITE_OK ){ Pager *pPager; - aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); - if( !aNew->pSchema ){ + pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt); + if( !pNew->pSchema ){ rc = SQLITE_NOMEM_BKPT; - }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){ zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } - sqlite3BtreeEnter(aNew->pBt); - pPager = sqlite3BtreePager(aNew->pBt); + sqlite3BtreeEnter(pNew->pBt); + pPager = sqlite3BtreePager(pNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); - sqlite3BtreeSecureDelete(aNew->pBt, + sqlite3BtreeSecureDelete(pNew->pBt, sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); #ifndef SQLITE_OMIT_PAGER_PRAGMAS - sqlite3BtreeSetPagerFlags(aNew->pBt, + sqlite3BtreeSetPagerFlags(pNew->pBt, PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK)); #endif - sqlite3BtreeLeave(aNew->pBt); + sqlite3BtreeLeave(pNew->pBt); } - aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - aNew->zDbSName = sqlite3DbStrDup(db, zName); - if( rc==SQLITE_OK && aNew->zDbSName==0 ){ + pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; + pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -99121,11 +100130,6 @@ static void detachFunc( sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); goto detach_error; } - if( !db->autoCommit ){ - sqlite3_snprintf(sizeof(zErr), zErr, - "cannot DETACH database within transaction"); - goto detach_error; - } if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){ sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); goto detach_error; @@ -99538,11 +100542,9 @@ SQLITE_PRIVATE int sqlite3AuthReadCol( #endif ); if( rc==SQLITE_DENY ){ - if( db->nDb>2 || iDb!=0 ){ - sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol); - }else{ - sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol); - } + char *z = sqlite3_mprintf("%s.%s", zTab, zCol); + if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z); + sqlite3ErrorMsg(pParse, "access to %z is prohibited", z); pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){ sqliteAuthBadReturnCode(pParse); @@ -100175,7 +101177,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char } freeIndex(db, pIndex); } - db->flags |= SQLITE_InternChanges; + db->mDbFlags |= DBFLAG_SchemaChange; } /* @@ -100210,28 +101212,26 @@ SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ /* ** Reset the schema for the database at index iDb. Also reset the -** TEMP schema. +** TEMP schema. The reset is deferred if db->nSchemaLock is not zero. +** Deferred resets may be run by calling with iDb<0. */ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ - Db *pDb; + int i; assert( iDb<db->nDb ); - /* Case 1: Reset the single schema identified by iDb */ - pDb = &db->aDb[iDb]; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); + if( iDb>=0 ){ + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + DbSetProperty(db, iDb, DB_ResetWanted); + DbSetProperty(db, 1, DB_ResetWanted); + } - /* If any database other than TEMP is reset, then also reset TEMP - ** since TEMP might be holding triggers that reference tables in the - ** other database. - */ - if( iDb!=1 ){ - pDb = &db->aDb[1]; - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); + if( db->nSchemaLock==0 ){ + for(i=0; i<db->nDb; i++){ + if( DbHasProperty(db, i, DB_ResetWanted) ){ + sqlite3SchemaClear(db->aDb[i].pSchema); + } + } } - return; } /* @@ -100241,13 +101241,14 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ int i; sqlite3BtreeEnterAll(db); + assert( db->nSchemaLock==0 ); for(i=0; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ sqlite3SchemaClear(pDb->pSchema); } } - db->flags &= ~SQLITE_InternChanges; + db->mDbFlags &= ~DBFLAG_SchemaChange; sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); sqlite3CollapseDatabaseArray(db); @@ -100257,7 +101258,7 @@ SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ ** This routine is called when a commit occurs. */ SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){ - db->flags &= ~SQLITE_InternChanges; + db->mDbFlags &= ~DBFLAG_SchemaChange; } /* @@ -100295,13 +101296,16 @@ SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){ */ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; - TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */ +#ifdef SQLITE_DEBUG /* Record the number of outstanding lookaside allocations in schema Tables ** prior to doing any free() operations. Since schema Tables do not use ** lookaside, this number should not change. */ - TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ? - db->lookaside.nOut : 0 ); + int nLookaside = 0; + if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){ + nLookaside = sqlite3LookasideUsed(db, 0); + } +#endif /* Delete all indices associated with this table. */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ @@ -100335,7 +101339,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){ sqlite3DbFree(db, pTable); /* Verify that no lookaside memory was used by schema tables */ - assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); + assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) ); } SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Do not delete the table until the reference count reaches zero. */ @@ -100361,7 +101365,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char pDb = &db->aDb[iDb]; p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0); sqlite3DeleteTable(db, p); - db->flags |= SQLITE_InternChanges; + db->mDbFlags |= DBFLAG_SchemaChange; } /* @@ -100474,7 +101478,8 @@ SQLITE_PRIVATE int sqlite3TwoPartName( return -1; } }else{ - assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0); + assert( db->init.iDb==0 || db->init.busy + || (db->mDbFlags & DBFLAG_Vacuum)!=0); iDb = db->init.iDb; *pUnqual = pName1; } @@ -100635,7 +101640,11 @@ SQLITE_PRIVATE void sqlite3StartTable( pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nTabRef = 1; +#ifdef SQLITE_DEFAULT_ROWEST + pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST); +#else pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); +#endif assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; @@ -100702,7 +101711,8 @@ SQLITE_PRIVATE void sqlite3StartTable( }else #endif { - pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2); + pParse->addrCrTab = + sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY); } sqlite3OpenMasterTable(pParse, iDb); sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); @@ -100751,12 +101761,10 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ Column *pCol; sqlite3 *db = pParse->db; if( (p = pParse->pNewTable)==0 ) return; -#if SQLITE_MAX_COLUMN if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); return; } -#endif z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); if( z==0 ) return; memcpy(z, pName->z, pName->n); @@ -101362,9 +102370,8 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){ ** Changes include: ** ** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL. -** (2) Convert the OP_CreateTable into an OP_CreateIndex. There is -** no rowid btree for a WITHOUT ROWID. Instead, the canonical -** data storage is a covering index btree. +** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY +** into BTREE_BLOBKEY. ** (3) Bypass the creation of the sqlite_master table entry ** for the PRIMARY KEY as the primary key index is now ** identified by the sqlite_master table entry of the table itself. @@ -101372,7 +102379,7 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){ ** schema to the rootpage from the main table. ** (5) Add all table columns to the PRIMARY KEY Index object ** so that the PRIMARY KEY is a covering index. The surplus -** columns are part of KeyInfo.nXField and are not used for +** columns are part of KeyInfo.nAllField and are not used for ** sorting or lookup or uniqueness checks. ** (6) Replace the rowid tail on all automatically generated UNIQUE ** indices with the PRIMARY KEY columns. @@ -101401,13 +102408,12 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ ** virtual tables */ if( IN_DECLARE_VTAB ) return; - /* Convert the OP_CreateTable opcode that would normally create the - ** root-page for the table into an OP_CreateIndex opcode. The index - ** created will become the PRIMARY KEY index. + /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY + ** into BTREE_BLOBKEY. */ if( pParse->addrCrTab ){ assert( v ); - sqlite3VdbeChangeOpcode(v, pParse->addrCrTab, OP_CreateIndex); + sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY); } /* Locate the PRIMARY KEY index. Or, if this table was originally @@ -101430,15 +102436,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ }else{ pPk = sqlite3PrimaryKeyIndex(pTab); - /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master - ** table entry. This is only required if currently generating VDBE - ** code for a CREATE TABLE (not when parsing one as part of reading - ** a database schema). */ - if( v ){ - assert( db->init.busy==0 ); - sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto); - } - /* ** Remove all redundant columns from the PRIMARY KEY. For example, change ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later @@ -101458,6 +102455,15 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ if( !db->init.imposterTable ) pPk->uniqNotNull = 1; nPk = pPk->nKeyCol; + /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master + ** table entry. This is only required if currently generating VDBE + ** code for a CREATE TABLE (not when parsing one as part of reading + ** a database schema). */ + if( v && pPk->tnum>0 ){ + assert( db->init.busy==0 ); + sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto); + } + /* The root page of the PRIMARY KEY is the table root page */ pPk->tnum = pTab->tnum; @@ -101747,7 +102753,7 @@ SQLITE_PRIVATE void sqlite3EndTable( return; } pParse->pNewTable = 0; - db->flags |= SQLITE_InternChanges; + db->mDbFlags |= DBFLAG_SchemaChange; #ifndef SQLITE_OMIT_ALTERTABLE if( !p->pSelect ){ @@ -101846,6 +102852,9 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + int rc; +#endif #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth; /* Saved xAuth pointer */ #endif @@ -101853,8 +102862,11 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ assert( pTable ); #ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3VtabCallConnect(pParse, pTable) ){ - return SQLITE_ERROR; + db->nSchemaLock++; + rc = sqlite3VtabCallConnect(pParse, pTable); + db->nSchemaLock--; + if( rc ){ + return 1; } if( IsVirtual(pTable) ) return 0; #endif @@ -102050,14 +103062,6 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ ** is also added (this can happen with an auto-vacuum database). */ static void destroyTable(Parse *pParse, Table *pTab){ -#ifdef SQLITE_OMIT_AUTOVACUUM - Index *pIdx; - int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - destroyRootPage(pParse, pTab->tnum, iDb); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - destroyRootPage(pParse, pIdx->tnum, iDb); - } -#else /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM ** is not defined), then it is important to call OP_Destroy on the ** table and index root-pages in order, starting with the numerically @@ -102100,7 +103104,6 @@ static void destroyTable(Parse *pParse, Table *pTab){ iDestroyed = iLargest; } } -#endif } /* @@ -102527,7 +103530,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); + sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx); sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); @@ -103016,7 +104019,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( sqlite3OomFault(db); goto exit_create_index; } - db->flags |= SQLITE_InternChanges; + db->mDbFlags |= DBFLAG_SchemaChange; if( pTblName!=0 ){ pIndex->tnum = db->init.newTnum; } @@ -103052,7 +104055,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( ** that case the convertToWithoutRowidTable() routine will replace ** the Noop with a Goto to jump over the VDBE code generated below. */ pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop); - sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); + sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY); /* Gather the complete text of the CREATE INDEX statement into ** the zStmt variable @@ -103464,12 +104467,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( pDatabase = 0; } if( pDatabase ){ - Token *pTemp = pDatabase; - pDatabase = pTable; - pTable = pTemp; + pItem->zName = sqlite3NameFromToken(db, pDatabase); + pItem->zDatabase = sqlite3NameFromToken(db, pTable); + }else{ + pItem->zName = sqlite3NameFromToken(db, pTable); + pItem->zDatabase = 0; } - pItem->zName = sqlite3NameFromToken(db, pTable); - pItem->zDatabase = sqlite3NameFromToken(db, pDatabase); return pList; } @@ -103574,8 +104577,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( */ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ assert( pIndexedBy!=0 ); - if( p && ALWAYS(p->nSrc>0) ){ - struct SrcList_item *pItem = &p->a[p->nSrc-1]; + if( p && pIndexedBy->n>0 ){ + struct SrcList_item *pItem; + assert( p->nSrc>0 ); + pItem = &p->a[p->nSrc-1]; assert( pItem->fg.notIndexed==0 ); assert( pItem->fg.isIndexedBy==0 ); assert( pItem->fg.isTabFunc==0 ); @@ -103585,7 +104590,7 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI pItem->fg.notIndexed = 1; }else{ pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy); - pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0); + pItem->fg.isIndexedBy = 1; } } } @@ -103658,36 +104663,25 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){ } /* -** Generate VDBE code for a COMMIT statement. +** Generate VDBE code for a COMMIT or ROLLBACK statement. +** Code for ROLLBACK is generated if eType==TK_ROLLBACK. Otherwise +** code is generated for a COMMIT. */ -SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){ +SQLITE_PRIVATE void sqlite3EndTransaction(Parse *pParse, int eType){ Vdbe *v; + int isRollback; assert( pParse!=0 ); assert( pParse->db!=0 ); - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){ + assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK ); + isRollback = eType==TK_ROLLBACK; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, + isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){ return; } v = sqlite3GetVdbe(pParse); if( v ){ - sqlite3VdbeAddOp1(v, OP_AutoCommit, 1); - } -} - -/* -** Generate VDBE code for a ROLLBACK statement. -*/ -SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){ - Vdbe *v; - - assert( pParse!=0 ); - assert( pParse->db!=0 ); - if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){ - return; - } - v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1); + sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, isRollback); } } @@ -103877,7 +104871,9 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint( assert( pIdx->aiColumn[j]>=0 ); zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); - sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol); + sqlite3StrAccumAppendAll(&errMsg, pTab->zName); + sqlite3StrAccumAppend(&errMsg, ".", 1); + sqlite3StrAccumAppendAll(&errMsg, zCol); } } zErr = sqlite3StrAccumFinish(&errMsg); @@ -104266,7 +105262,7 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq( ** from the main database is substituted, if one is available. */ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ - if( pColl ){ + if( pColl && pColl->xCmp==0 ){ const char *zName = pColl->zName; sqlite3 *db = pParse->db; CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName); @@ -104302,8 +105298,8 @@ static CollSeq *findCollSeqEntry( pColl = sqlite3HashFind(&db->aCollSeq, zName); if( 0==pColl && create ){ - int nName = sqlite3Strlen30(zName); - pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1); + int nName = sqlite3Strlen30(zName) + 1; + pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName); if( pColl ){ CollSeq *pDel = 0; pColl[0].zName = (char*)&pColl[3]; @@ -104313,7 +105309,6 @@ static CollSeq *findCollSeqEntry( pColl[2].zName = (char*)&pColl[3]; pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); - pColl[0].zName[nName] = 0; pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl); /* If a malloc() failure occurred in sqlite3HashInsert(), it will @@ -104453,7 +105448,8 @@ SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs( FuncDef *pOther; const char *zName = aDef[i].zName; int nName = sqlite3Strlen30(zName); - int h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; + int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ; + assert( zName[0]>='a' && zName[0]<='z' ); pOther = functionSearch(h, zName); if( pOther ){ assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] ); @@ -104519,7 +105515,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction( /* If no match is found, search the built-in functions. ** - ** If the SQLITE_PreferBuiltin flag is set, then search the built-in + ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in ** functions even if a prior app-defined function was found. And give ** priority to built-in functions. ** @@ -104529,7 +105525,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction( ** new function. But the FuncDefs for built-in functions are read-only. ** So we must not search for built-ins when creating a new function. */ - if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ + if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ bestScore = 0; h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; p = functionSearch(h, zName); @@ -104602,8 +105598,8 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){ pSchema->pSeqTab = 0; if( pSchema->schemaFlags & DB_SchemaLoaded ){ pSchema->iGeneration++; - pSchema->schemaFlags &= ~DB_SchemaLoaded; } + pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted); } /* @@ -104986,7 +105982,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** API function sqlite3_count_changes) to be set incorrectly. ** ** The "rcauth==SQLITE_OK" terms is the - ** IMPLEMENATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and + ** IMPLEMENTATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and ** the callback returns SQLITE_IGNORE then the DELETE operation proceeds but ** the truncate optimization is disabled and all rows are deleted ** individually. @@ -105092,7 +106088,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); }else{ /* Add the rowid of the row to be deleted to the RowSet */ - nKey = 1; /* OP_Seek always uses a single rowid */ + nKey = 1; /* OP_DeferredSeek always uses a single rowid */ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); } } @@ -105135,7 +106131,11 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); + if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey); + }else{ + sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); + } assert( nKey==0 ); /* OP_Found will use a composite key */ }else{ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); @@ -105485,10 +106485,11 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ *piPartIdxLabel = sqlite3VdbeMakeLabel(v); - pParse->iSelfTab = iDataCur; + pParse->iSelfTab = iDataCur + 1; sqlite3ExprCachePush(pParse); sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, SQLITE_JUMPIFNULL); + pParse->iSelfTab = 0; }else{ *piPartIdxLabel = 0; } @@ -105616,16 +106617,20 @@ static void typeofFunc( int NotUsed, sqlite3_value **argv ){ - const char *z = 0; + static const char *azType[] = { "integer", "real", "text", "blob", "null" }; + int i = sqlite3_value_type(argv[0]) - 1; UNUSED_PARAMETER(NotUsed); - switch( sqlite3_value_type(argv[0]) ){ - case SQLITE_INTEGER: z = "integer"; break; - case SQLITE_TEXT: z = "text"; break; - case SQLITE_FLOAT: z = "real"; break; - case SQLITE_BLOB: z = "blob"; break; - default: z = "null"; break; - } - sqlite3_result_text(context, z, -1, SQLITE_STATIC); + assert( i>=0 && i<ArraySize(azType) ); + assert( SQLITE_INTEGER==1 ); + assert( SQLITE_FLOAT==2 ); + assert( SQLITE_TEXT==3 ); + assert( SQLITE_BLOB==4 ); + assert( SQLITE_NULL==5 ); + /* EVIDENCE-OF: R-01470-60482 The sqlite3_value_type(V) interface returns + ** the datatype code for the initial datatype of the sqlite3_value object + ** V. The returned value is one of SQLITE_INTEGER, SQLITE_FLOAT, + ** SQLITE_TEXT, SQLITE_BLOB, or SQLITE_NULL. */ + sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC); } @@ -106401,7 +107406,8 @@ static void likeFunc( #ifdef SQLITE_TEST sqlite3_like_count++; #endif - sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); + sqlite3_result_int(context, + patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); } } @@ -107242,9 +108248,14 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) /* ** pExpr points to an expression which implements a function. If ** it is appropriate to apply the LIKE optimization to that function -** then set aWc[0] through aWc[2] to the wildcard characters and -** return TRUE. If the function is not a LIKE-style function then -** return FALSE. +** then set aWc[0] through aWc[2] to the wildcard characters and the +** escape character and then return TRUE. If the function is not a +** LIKE-style function then return FALSE. +** +** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE +** operator if c is a string literal that is exactly one byte in length. +** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is +** no ESCAPE clause. ** ** *pIsNocase is set to true if uppercase and lowercase are equivalent for ** the function (default for LIKE). If the function makes the distinction @@ -107253,17 +108264,26 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive) */ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; - if( pExpr->op!=TK_FUNCTION - || !pExpr->x.pList - || pExpr->x.pList->nExpr!=2 - ){ + int nExpr; + if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0); + nExpr = pExpr->x.pList->nExpr; + pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ return 0; } + if( nExpr<3 ){ + aWc[3] = 0; + }else{ + Expr *pEscape = pExpr->x.pList->a[2].pExpr; + char *zEscape; + if( pEscape->op!=TK_STRING ) return 0; + zEscape = pEscape->u.zToken; + if( zEscape[0]==0 || zEscape[1]!=0 ) return 0; + aWc[3] = zEscape[0]; + } /* The memcpy() statement assumes that the wildcard characters are ** the first three statements in the compareInfo structure. The @@ -108046,10 +109066,12 @@ static void fkScanChildren( /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment either the deferred or immediate ** foreign key constraint counter. */ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); - sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); - if( pWInfo ){ - sqlite3WhereEnd(pWInfo); + if( pParse->nErr==0 ){ + pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); + sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); + if( pWInfo ){ + sqlite3WhereEnd(pWInfo); + } } /* Clean up the WHERE clause constructed above. */ @@ -109061,7 +110083,7 @@ static int autoIncBegin( ){ int memId = 0; /* Register holding maximum rowid */ if( (pTab->tabFlags & TF_Autoincrement)!=0 - && (pParse->db->flags & SQLITE_Vacuum)==0 + && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; @@ -109319,7 +110341,6 @@ SQLITE_PRIVATE void sqlite3Insert( ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ - char *zTab; /* Name of the table into which we are inserting */ int i, j; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ @@ -109356,10 +110377,10 @@ SQLITE_PRIVATE void sqlite3Insert( #endif db = pParse->db; - memset(&dest, 0, sizeof(dest)); if( pParse->nErr || db->mallocFailed ){ goto insert_cleanup; } + dest.iSDParm = 0; /* Suppress a harmless compiler warning */ /* If the Select object is really just a simple VALUES() list with a ** single row (the common case) then keep that one row of values @@ -109375,8 +110396,6 @@ SQLITE_PRIVATE void sqlite3Insert( /* Locate the table into which we will be inserting new information. */ assert( pTabList->nSrc==1 ); - zTab = pTabList->a[0].zName; - if( NEVER(zTab==0) ) goto insert_cleanup; pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ){ goto insert_cleanup; @@ -110168,7 +111187,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; - pParse->ckBase = regNewData+1; + pParse->iSelfTab = -(regNewData+1); onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk; @@ -110188,6 +111207,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( } sqlite3VdbeResolveLabel(v, allOk); } + pParse->iSelfTab = 0; } #endif /* !defined(SQLITE_OMIT_CHECK) */ @@ -110332,10 +111352,10 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Skip partial indices for which the WHERE clause is not true */ if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]); - pParse->ckBase = regNewData+1; + pParse->iSelfTab = -(regNewData+1); sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk, SQLITE_JUMPIFNULL); - pParse->ckBase = 0; + pParse->iSelfTab = 0; } /* Create a record for this index entry as it should appear after @@ -110346,9 +111366,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int iField = pIdx->aiColumn[i]; int x; if( iField==XN_EXPR ){ - pParse->ckBase = regNewData+1; + pParse->iSelfTab = -(regNewData+1); sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); - pParse->ckBase = 0; + pParse->iSelfTab = 0; VdbeComment((v, "%s column %d", pIdx->zName, i)); }else{ if( iField==XN_ROWID || iField==pTab->iPKey ){ @@ -110733,7 +111753,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ } if( pSrc->aiColumn[i]==XN_EXPR ){ assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); - if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, + if( sqlite3ExprCompare(0, pSrc->aColExpr->a[i].pExpr, pDest->aColExpr->a[i].pExpr, -1)!=0 ){ return 0; /* Different expressions in the index */ } @@ -110745,7 +111765,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ return 0; /* Different collating sequences */ } } - if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){ + if( sqlite3ExprCompare(0, pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){ return 0; /* Different WHERE clauses */ } @@ -110893,7 +111913,7 @@ static int xferOptimization( Column *pDestCol = &pDest->aCol[i]; Column *pSrcCol = &pSrc->aCol[i]; #ifdef SQLITE_ENABLE_HIDDEN_COLUMNS - if( (db->flags & SQLITE_Vacuum)==0 + if( (db->mDbFlags & DBFLAG_Vacuum)==0 && (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN ){ return 0; /* Neither table may have __hidden__ columns */ @@ -110969,15 +111989,15 @@ static int xferOptimization( regRowid = sqlite3GetTempReg(pParse); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (db->flags & SQLITE_Vacuum)==0 && ( + if( (db->mDbFlags & DBFLAG_Vacuum)==0 && ( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ || destHasUniqueIdx /* (2) */ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ )){ /* In some circumstances, we are able to run the xfer optimization ** only if the destination table is initially empty. Unless the - ** SQLITE_Vacuum flag is set, this block generates code to make - ** that determination. If SQLITE_Vacuum is set, then the destination + ** DBFLAG_Vacuum flag is set, this block generates code to make + ** that determination. If DBFLAG_Vacuum is set, then the destination ** table is always empty. ** ** Conditions under which the destination must be empty: @@ -111013,8 +112033,8 @@ static int xferOptimization( assert( (pDest->tabFlags & TF_Autoincrement)==0 ); } sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - if( db->flags & SQLITE_Vacuum ){ - sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + if( db->mDbFlags & DBFLAG_Vacuum ){ + sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| OPFLAG_APPEND|OPFLAG_USESEEKRESULT; }else{ @@ -111045,13 +112065,13 @@ static int xferOptimization( VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - if( db->flags & SQLITE_Vacuum ){ + if( db->mDbFlags & DBFLAG_Vacuum ){ /* This INSERT command is part of a VACUUM operation, which guarantees ** that the destination table is empty. If all indexed columns use ** collation sequence BINARY, then it can also be assumed that the ** index will be populated by inserting keys in strictly sorted ** order. In this case, instead of seeking within the b-tree as part - ** of every OP_IdxInsert opcode, an OP_Last is added before the + ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the ** OP_IdxInsert to seek to the point within the b-tree where each key ** should be inserted. This is faster. ** @@ -111066,7 +112086,7 @@ static int xferOptimization( } if( i==pSrcIdx->nColumn ){ idxInsFlags = OPFLAG_USESEEKRESULT; - sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); } } if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ @@ -111225,11 +112245,8 @@ exec_out: rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && pzErrMsg ){ - int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); - *pzErrMsg = sqlite3Malloc(nErrMsg); - if( *pzErrMsg ){ - memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg); - }else{ + *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db)); + if( *pzErrMsg==0 ){ rc = SQLITE_NOMEM_BKPT; sqlite3Error(db, SQLITE_NOMEM); } @@ -111400,7 +112417,7 @@ struct sqlite3_api_routines { int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, const char*,const char*),void*); void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); - char * (*snprintf)(int,char*,const char*,...); + char * (*xsnprintf)(int,char*,const char*,...); int (*step)(sqlite3_stmt*); int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, char const**,char const**,int*,int*,int*); @@ -111512,7 +112529,7 @@ struct sqlite3_api_routines { int (*uri_boolean)(const char*,const char*,int); sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); const char *(*uri_parameter)(const char*,const char*); - char *(*vsnprintf)(int,char*,const char*,va_list); + char *(*xvsnprintf)(int,char*,const char*,va_list); int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); /* Version 3.8.7 and later */ int (*auto_extension)(void(*)(void)); @@ -111550,6 +112567,14 @@ struct sqlite3_api_routines { char *(*expanded_sql)(sqlite3_stmt*); /* Version 3.18.0 and later */ void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64); + /* Version 3.20.0 and later */ + int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, + sqlite3_stmt**,const char**); + int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, + sqlite3_stmt**,const void**); + int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); + void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); + void *(*value_pointer)(sqlite3_value*,const char*); }; /* @@ -111676,7 +112701,7 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_rollback_hook sqlite3_api->rollback_hook #define sqlite3_set_authorizer sqlite3_api->set_authorizer #define sqlite3_set_auxdata sqlite3_api->set_auxdata -#define sqlite3_snprintf sqlite3_api->snprintf +#define sqlite3_snprintf sqlite3_api->xsnprintf #define sqlite3_step sqlite3_api->step #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup @@ -111700,7 +112725,7 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_value_text16le sqlite3_api->value_text16le #define sqlite3_value_type sqlite3_api->value_type #define sqlite3_vmprintf sqlite3_api->vmprintf -#define sqlite3_vsnprintf sqlite3_api->vsnprintf +#define sqlite3_vsnprintf sqlite3_api->xvsnprintf #define sqlite3_overload_function sqlite3_api->overload_function #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 @@ -111776,7 +112801,7 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_uri_boolean sqlite3_api->uri_boolean #define sqlite3_uri_int64 sqlite3_api->uri_int64 #define sqlite3_uri_parameter sqlite3_api->uri_parameter -#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf +#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 /* Version 3.8.7 and later */ #define sqlite3_auto_extension sqlite3_api->auto_extension @@ -111810,6 +112835,12 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_expanded_sql sqlite3_api->expanded_sql /* Version 3.18.0 and later */ #define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid +/* Version 3.20.0 and later */ +#define sqlite3_prepare_v3 sqlite3_api->prepare_v3 +#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3 +#define sqlite3_bind_pointer sqlite3_api->bind_pointer +#define sqlite3_result_pointer sqlite3_api->result_pointer +#define sqlite3_value_pointer sqlite3_api->value_pointer #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -111865,6 +112896,7 @@ typedef int (*sqlite3_loadext_entry)( # define sqlite3_open16 0 # define sqlite3_prepare16 0 # define sqlite3_prepare16_v2 0 +# define sqlite3_prepare16_v3 0 # define sqlite3_result_error16 0 # define sqlite3_result_text16 0 # define sqlite3_result_text16be 0 @@ -112237,7 +113269,13 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_trace_v2, sqlite3_expanded_sql, /* Version 3.18.0 and later */ - sqlite3_set_last_insert_rowid + sqlite3_set_last_insert_rowid, + /* Version 3.20.0 and later */ + sqlite3_prepare_v3, + sqlite3_prepare16_v3, + sqlite3_bind_pointer, + sqlite3_result_pointer, + sqlite3_value_pointer }; /* @@ -112659,35 +113697,38 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ #define PragTyp_ENCODING 12 #define PragTyp_FOREIGN_KEY_CHECK 13 #define PragTyp_FOREIGN_KEY_LIST 14 -#define PragTyp_INCREMENTAL_VACUUM 15 -#define PragTyp_INDEX_INFO 16 -#define PragTyp_INDEX_LIST 17 -#define PragTyp_INTEGRITY_CHECK 18 -#define PragTyp_JOURNAL_MODE 19 -#define PragTyp_JOURNAL_SIZE_LIMIT 20 -#define PragTyp_LOCK_PROXY_FILE 21 -#define PragTyp_LOCKING_MODE 22 -#define PragTyp_PAGE_COUNT 23 -#define PragTyp_MMAP_SIZE 24 -#define PragTyp_OPTIMIZE 25 -#define PragTyp_PAGE_SIZE 26 -#define PragTyp_SECURE_DELETE 27 -#define PragTyp_SHRINK_MEMORY 28 -#define PragTyp_SOFT_HEAP_LIMIT 29 -#define PragTyp_SYNCHRONOUS 30 -#define PragTyp_TABLE_INFO 31 -#define PragTyp_TEMP_STORE 32 -#define PragTyp_TEMP_STORE_DIRECTORY 33 -#define PragTyp_THREADS 34 -#define PragTyp_WAL_AUTOCHECKPOINT 35 -#define PragTyp_WAL_CHECKPOINT 36 -#define PragTyp_ACTIVATE_EXTENSIONS 37 -#define PragTyp_HEXKEY 38 -#define PragTyp_KEY 39 -#define PragTyp_REKEY 40 -#define PragTyp_LOCK_STATUS 41 -#define PragTyp_PARSER_TRACE 42 -#define PragTyp_STATS 43 +#define PragTyp_FUNCTION_LIST 15 +#define PragTyp_INCREMENTAL_VACUUM 16 +#define PragTyp_INDEX_INFO 17 +#define PragTyp_INDEX_LIST 18 +#define PragTyp_INTEGRITY_CHECK 19 +#define PragTyp_JOURNAL_MODE 20 +#define PragTyp_JOURNAL_SIZE_LIMIT 21 +#define PragTyp_LOCK_PROXY_FILE 22 +#define PragTyp_LOCKING_MODE 23 +#define PragTyp_PAGE_COUNT 24 +#define PragTyp_MMAP_SIZE 25 +#define PragTyp_MODULE_LIST 26 +#define PragTyp_OPTIMIZE 27 +#define PragTyp_PAGE_SIZE 28 +#define PragTyp_PRAGMA_LIST 29 +#define PragTyp_SECURE_DELETE 30 +#define PragTyp_SHRINK_MEMORY 31 +#define PragTyp_SOFT_HEAP_LIMIT 32 +#define PragTyp_SYNCHRONOUS 33 +#define PragTyp_TABLE_INFO 34 +#define PragTyp_TEMP_STORE 35 +#define PragTyp_TEMP_STORE_DIRECTORY 36 +#define PragTyp_THREADS 37 +#define PragTyp_WAL_AUTOCHECKPOINT 38 +#define PragTyp_WAL_CHECKPOINT 39 +#define PragTyp_ACTIVATE_EXTENSIONS 40 +#define PragTyp_HEXKEY 41 +#define PragTyp_KEY 42 +#define PragTyp_REKEY 43 +#define PragTyp_LOCK_STATUS 44 +#define PragTyp_PARSER_TRACE 45 +#define PragTyp_STATS 46 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -112733,26 +113774,29 @@ static const char *const pragCName[] = { /* 26 */ "seq", /* Used by: database_list */ /* 27 */ "name", /* 28 */ "file", - /* 29 */ "seq", /* Used by: collation_list */ - /* 30 */ "name", - /* 31 */ "id", /* Used by: foreign_key_list */ - /* 32 */ "seq", - /* 33 */ "table", - /* 34 */ "from", - /* 35 */ "to", - /* 36 */ "on_update", - /* 37 */ "on_delete", - /* 38 */ "match", - /* 39 */ "table", /* Used by: foreign_key_check */ - /* 40 */ "rowid", - /* 41 */ "parent", - /* 42 */ "fkid", - /* 43 */ "busy", /* Used by: wal_checkpoint */ - /* 44 */ "log", - /* 45 */ "checkpointed", - /* 46 */ "timeout", /* Used by: busy_timeout */ - /* 47 */ "database", /* Used by: lock_status */ - /* 48 */ "status", + /* 29 */ "name", /* Used by: function_list */ + /* 30 */ "builtin", + /* 31 */ "name", /* Used by: module_list pragma_list */ + /* 32 */ "seq", /* Used by: collation_list */ + /* 33 */ "name", + /* 34 */ "id", /* Used by: foreign_key_list */ + /* 35 */ "seq", + /* 36 */ "table", + /* 37 */ "from", + /* 38 */ "to", + /* 39 */ "on_update", + /* 40 */ "on_delete", + /* 41 */ "match", + /* 42 */ "table", /* Used by: foreign_key_check */ + /* 43 */ "rowid", + /* 44 */ "parent", + /* 45 */ "fkid", + /* 46 */ "busy", /* Used by: wal_checkpoint */ + /* 47 */ "log", + /* 48 */ "checkpointed", + /* 49 */ "timeout", /* Used by: busy_timeout */ + /* 50 */ "database", /* Used by: lock_status */ + /* 51 */ "status", }; /* Definitions of all built-in pragmas */ @@ -112798,7 +113842,7 @@ static const PragmaName aPragmaName[] = { {/* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 46, 1, + /* ColNames: */ 49, 1, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "cache_size", @@ -112835,7 +113879,7 @@ static const PragmaName aPragmaName[] = { {/* zName: */ "collation_list", /* ePragTyp: */ PragTyp_COLLATION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 29, 2, + /* ColNames: */ 32, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) @@ -112906,15 +113950,15 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) {/* zName: */ "foreign_key_check", /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 39, 4, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, + /* ColNames: */ 42, 4, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) {/* zName: */ "foreign_key_list", /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 31, 8, + /* ColNames: */ 34, 8, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -112945,6 +113989,15 @@ static const PragmaName aPragmaName[] = { /* ColNames: */ 0, 0, /* iArg: */ SQLITE_FullFSync }, #endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) +#if defined(SQLITE_INTROSPECTION_PRAGMAS) + {/* zName: */ "function_list", + /* ePragTyp: */ PragTyp_FUNCTION_LIST, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 29, 2, + /* iArg: */ 0 }, +#endif +#endif #if defined(SQLITE_HAS_CODEC) {/* zName: */ "hexkey", /* ePragTyp: */ PragTyp_HEXKEY, @@ -112993,7 +114046,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "integrity_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -113034,7 +114087,7 @@ static const PragmaName aPragmaName[] = { {/* zName: */ "lock_status", /* ePragTyp: */ PragTyp_LOCK_STATUS, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 47, 2, + /* ColNames: */ 50, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) @@ -113054,6 +114107,17 @@ static const PragmaName aPragmaName[] = { /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) +#if !defined(SQLITE_OMIT_VIRTUALTABLE) +#if defined(SQLITE_INTROSPECTION_PRAGMAS) + {/* zName: */ "module_list", + /* ePragTyp: */ PragTyp_MODULE_LIST, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 31, 1, + /* iArg: */ 0 }, +#endif +#endif +#endif {/* zName: */ "optimize", /* ePragTyp: */ PragTyp_OPTIMIZE, /* ePragFlg: */ PragFlg_Result1|PragFlg_NeedSchema, @@ -113078,6 +114142,13 @@ static const PragmaName aPragmaName[] = { /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif +#if defined(SQLITE_INTROSPECTION_PRAGMAS) + {/* zName: */ "pragma_list", + /* ePragTyp: */ PragTyp_PRAGMA_LIST, + /* ePragFlg: */ PragFlg_Result0, + /* ColNames: */ 31, 1, + /* iArg: */ 0 }, +#endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "query_only", /* ePragTyp: */ PragTyp_FLAG, @@ -113088,7 +114159,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_INTEGRITY_CHECK) {/* zName: */ "quick_check", /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1, /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif @@ -113097,7 +114168,7 @@ static const PragmaName aPragmaName[] = { /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ReadUncommitted }, + /* iArg: */ SQLITE_ReadUncommit }, {/* zName: */ "recursive_triggers", /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, @@ -113241,7 +114312,7 @@ static const PragmaName aPragmaName[] = { {/* zName: */ "wal_checkpoint", /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 43, 3, + /* ColNames: */ 46, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -113249,10 +114320,10 @@ static const PragmaName aPragmaName[] = { /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, + /* iArg: */ SQLITE_WriteSchema }, #endif }; -/* Number of pragmas: 60 on by default, 74 total. */ +/* Number of pragmas: 60 on by default, 77 total. */ /************** End of pragma.h **********************************************/ /************** Continuing where we left off in pragma.c *********************/ @@ -113525,16 +114596,16 @@ static const PragmaName *pragmaLocate(const char *zName){ /* ** Helper subroutine for PRAGMA integrity_check: ** -** Generate code to output a single-column result row with the result -** held in register regResult. Decrement the result count and halt if -** the maximum number of result rows have been issued. +** Generate code to output a single-column result row with a value of the +** string held in register 3. Decrement the result count in register 1 +** and halt if the maximum number of result rows have been issued. */ -static int integrityCheckResultRow(Vdbe *v, int regResult){ +static int integrityCheckResultRow(Vdbe *v){ int addr; - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeAddOp0(v, OP_Halt); return addr; } @@ -113742,18 +114813,22 @@ SQLITE_PRIVATE void sqlite3Pragma( /* ** PRAGMA [schema.]secure_delete - ** PRAGMA [schema.]secure_delete=ON/OFF + ** PRAGMA [schema.]secure_delete=ON/OFF/FAST ** ** The first form reports the current setting for the ** secure_delete flag. The second form changes the secure_delete - ** flag setting and reports thenew value. + ** flag setting and reports the new value. */ case PragTyp_SECURE_DELETE: { Btree *pBt = pDb->pBt; int b = -1; assert( pBt!=0 ); if( zRight ){ - b = sqlite3GetBoolean(zRight, 0); + if( sqlite3_stricmp(zRight, "fast")==0 ){ + b = 2; + }else{ + b = sqlite3GetBoolean(zRight, 0); + } } if( pId2->n==0 && b>=0 ){ int ii; @@ -114335,7 +115410,6 @@ SQLITE_PRIVATE void sqlite3Pragma( pCol->notNull ? 1 : 0, pCol->pDflt ? pCol->pDflt->u.zToken : 0, k); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); } } } @@ -114355,9 +115429,8 @@ SQLITE_PRIVATE void sqlite3Pragma( pTab->szTabRow, pTab->nRowLogEst, pTab->tabFlags); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeMultiLoad(v, 2, "siii", + sqlite3VdbeMultiLoad(v, 2, "siiiX", pIdx->zName, pIdx->szIdxRow, pIdx->aiRowLogEst[0], @@ -114390,10 +115463,10 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; i<mx; i++){ i16 cnum = pIdx->aiColumn[i]; - sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum, + sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum, cnum<0 ? 0 : pTab->aCol[cnum].zName); if( pPragma->iArg ){ - sqlite3VdbeMultiLoad(v, 4, "isi", + sqlite3VdbeMultiLoad(v, 4, "isiX", pIdx->aSortOrder[i], pIdx->azColl[i], i<pIdx->nKeyCol); @@ -114420,7 +115493,6 @@ SQLITE_PRIVATE void sqlite3Pragma( IsUniqueIndex(pIdx), azOrigin[pIdx->idxType], pIdx->pPartIdxWhere!=0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); } } } @@ -114436,7 +115508,6 @@ SQLITE_PRIVATE void sqlite3Pragma( i, db->aDb[i].zDbSName, sqlite3BtreeGetFilename(db->aDb[i].pBt)); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } } break; @@ -114448,10 +115519,49 @@ SQLITE_PRIVATE void sqlite3Pragma( for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } } break; + +#ifdef SQLITE_INTROSPECTION_PRAGMAS + case PragTyp_FUNCTION_LIST: { + int i; + HashElem *j; + FuncDef *p; + pParse->nMem = 2; + for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ + for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){ + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); + } + } + for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){ + p = (FuncDef*)sqliteHashData(j); + sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0); + } + } + break; + +#ifndef SQLITE_OMIT_VIRTUALTABLE + case PragTyp_MODULE_LIST: { + HashElem *j; + pParse->nMem = 1; + for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){ + Module *pMod = (Module*)sqliteHashData(j); + sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName); + } + } + break; +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + + case PragTyp_PRAGMA_LIST: { + int i; + for(i=0; i<ArraySize(aPragmaName); i++){ + sqlite3VdbeMultiLoad(v, 1, "s", aPragmaName[i].zName); + } + } + break; +#endif /* SQLITE_INTROSPECTION_PRAGMAS */ + #endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ #ifndef SQLITE_OMIT_FOREIGN_KEY @@ -114477,7 +115587,6 @@ SQLITE_PRIVATE void sqlite3Pragma( actionName(pFK->aAction[1]), /* ON UPDATE */ actionName(pFK->aAction[0]), /* ON DELETE */ "NONE"); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8); } ++i; pFK = pFK->pNextFrom; @@ -114587,7 +115696,7 @@ SQLITE_PRIVATE void sqlite3Pragma( }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1); } - sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1); + sqlite3VdbeMultiLoad(v, regResult+2, "siX", pFK->zTo, i-1); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4); sqlite3VdbeResolveLabel(v, addrOk); sqlite3DbFree(db, aiCols); @@ -114673,12 +115782,11 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Do an integrity check on each database file */ for(i=0; i<db->nDb; i++){ - HashElem *x; - Hash *pTbls; - int *aRoot; - int cnt = 0; - int mxIdx = 0; - int nIdx; + HashElem *x; /* For looping over tables in the schema */ + Hash *pTbls; /* Set of all tables in the schema */ + int *aRoot; /* Array of root page numbers of all btrees */ + int cnt = 0; /* Number of entries in aRoot[] */ + int mxIdx = 0; /* Maximum number of indexes for any table */ if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; @@ -114693,8 +115801,9 @@ SQLITE_PRIVATE void sqlite3Pragma( assert( sqlite3SchemaMutexHeld(db, i, 0) ); pTbls = &db->aDb[i].pSchema->tblHash; for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ - Table *pTab = sqliteHashData(x); - Index *pIdx; + Table *pTab = sqliteHashData(x); /* Current table */ + Index *pIdx; /* An index on pTab */ + int nIdx; /* Number of indexes on pTab */ if( HasRowid(pTab) ) cnt++; for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; } if( nIdx>mxIdx ) mxIdx = nIdx; @@ -114704,15 +115813,16 @@ SQLITE_PRIVATE void sqlite3Pragma( for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; - if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum; + if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - aRoot[cnt++] = pIdx->tnum; + aRoot[++cnt] = pIdx->tnum; } } - aRoot[cnt] = 0; + aRoot[0] = cnt; /* Make sure sufficient number of registers have been allocated */ pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); + sqlite3ClearTempRegCache(pParse); /* Do the b-tree integrity checks */ sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); @@ -114721,9 +115831,8 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), P4_DYNAMIC); - sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); - integrityCheckResultRow(v, 2); + sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3); + integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, addr); /* Make sure all the indices are constructed correctly. @@ -114737,16 +115846,13 @@ SQLITE_PRIVATE void sqlite3Pragma( int r1 = -1; if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ - if( pTab->pCheck==0 - && (pTab->tabFlags & TF_HasNotNull)==0 - && (pTab->pIndex==0 || isQuick) - ){ - continue; /* No additional checks needed for this table */ - } pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); sqlite3ExprCacheClear(pParse); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, 1, 0, &iDataCur, &iIdxCur); + /* reg[7] counts the number of entries in the table. + ** reg[8+i] counts the number of entries in the i-th index + */ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */ @@ -114767,7 +115873,7 @@ SQLITE_PRIVATE void sqlite3Pragma( zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, pTab->aCol[j].zName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v, 3); + integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, jmp2); } /* Verify CHECK constraints */ @@ -114778,7 +115884,7 @@ SQLITE_PRIVATE void sqlite3Pragma( int addrCkOk = sqlite3VdbeMakeLabel(v); char *zErr; int k; - pParse->iSelfTab = iDataCur; + pParse->iSelfTab = iDataCur + 1; sqlite3ExprCachePush(pParse); for(k=pCheck->nExpr-1; k>0; k--){ sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); @@ -114786,60 +115892,66 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, SQLITE_JUMPIFNULL); sqlite3VdbeResolveLabel(v, addrCkFault); + pParse->iSelfTab = 0; zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", pTab->zName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v, 3); + integrityCheckResultRow(v); sqlite3VdbeResolveLabel(v, addrCkOk); sqlite3ExprCachePop(pParse); } sqlite3ExprListDelete(db, pCheck); } - /* Validate index entries for the current row */ - for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){ - int jmp2, jmp3, jmp4, jmp5; - int ckUniq = sqlite3VdbeMakeLabel(v); - if( pPk==pIdx ) continue; - r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, - pPrior, r1); - pPrior = pIdx; - sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ - /* Verify that an index entry exists for the current table row */ - jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, - pIdx->nColumn); VdbeCoverage(v); - sqlite3VdbeLoadString(v, 3, "row "); - sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); - sqlite3VdbeLoadString(v, 4, " missing from index "); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); - jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); - jmp4 = integrityCheckResultRow(v, 3); - sqlite3VdbeJumpHere(v, jmp2); - /* For UNIQUE indexes, verify that only one entry exists with the - ** current key. The entry is unique if (1) any column is NULL - ** or (2) the next entry has a different key */ - if( IsUniqueIndex(pIdx) ){ - int uniqOk = sqlite3VdbeMakeLabel(v); - int jmp6; - int kk; - for(kk=0; kk<pIdx->nKeyCol; kk++){ - int iCol = pIdx->aiColumn[kk]; - assert( iCol!=XN_ROWID && iCol<pTab->nCol ); - if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; - sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); - VdbeCoverage(v); + if( !isQuick ){ /* Omit the remaining tests for quick_check */ + /* Sanity check on record header decoding */ + sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3); + sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); + /* Validate index entries for the current row */ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int jmp2, jmp3, jmp4, jmp5; + int ckUniq = sqlite3VdbeMakeLabel(v); + if( pPk==pIdx ) continue; + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, + pPrior, r1); + pPrior = pIdx; + sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */ + /* Verify that an index entry exists for the current table row */ + jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, + pIdx->nColumn); VdbeCoverage(v); + sqlite3VdbeLoadString(v, 3, "row "); + sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); + sqlite3VdbeLoadString(v, 4, " missing from index "); + sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); + jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); + sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); + jmp4 = integrityCheckResultRow(v); + sqlite3VdbeJumpHere(v, jmp2); + /* For UNIQUE indexes, verify that only one entry exists with the + ** current key. The entry is unique if (1) any column is NULL + ** or (2) the next entry has a different key */ + if( IsUniqueIndex(pIdx) ){ + int uniqOk = sqlite3VdbeMakeLabel(v); + int jmp6; + int kk; + for(kk=0; kk<pIdx->nKeyCol; kk++){ + int iCol = pIdx->aiColumn[kk]; + assert( iCol!=XN_ROWID && iCol<pTab->nCol ); + if( iCol>=0 && pTab->aCol[iCol].notNull ) continue; + sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk); + VdbeCoverage(v); + } + jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); + sqlite3VdbeGoto(v, uniqOk); + sqlite3VdbeJumpHere(v, jmp6); + sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, + pIdx->nKeyCol); VdbeCoverage(v); + sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); + sqlite3VdbeGoto(v, jmp5); + sqlite3VdbeResolveLabel(v, uniqOk); } - jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); - sqlite3VdbeGoto(v, uniqOk); - sqlite3VdbeJumpHere(v, jmp6); - sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, - pIdx->nKeyCol); VdbeCoverage(v); - sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); - sqlite3VdbeGoto(v, jmp5); - sqlite3VdbeResolveLabel(v, uniqOk); + sqlite3VdbeJumpHere(v, jmp4); + sqlite3ResolvePartIdxLabel(pParse, jmp3); } - sqlite3VdbeJumpHere(v, jmp4); - sqlite3ResolvePartIdxLabel(pParse, jmp3); } sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); @@ -114851,9 +115963,9 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - sqlite3VdbeLoadString(v, 3, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); - integrityCheckResultRow(v, 7); + sqlite3VdbeLoadString(v, 4, pIdx->zName); + sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3); + integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, addr); } } @@ -114867,6 +115979,9 @@ SQLITE_PRIVATE void sqlite3Pragma( { OP_IfNotZero, 1, 4, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ { OP_ResultRow, 3, 1, 0}, /* 3 */ + { OP_Halt, 0, 0, 0}, /* 4 */ + { OP_String8, 0, 3, 0}, /* 5 */ + { OP_Goto, 0, 3, 0}, /* 6 */ }; VdbeOp *aOp; @@ -114875,7 +115990,10 @@ SQLITE_PRIVATE void sqlite3Pragma( aOp[0].p2 = 1-mxErr; aOp[2].p4type = P4_STATIC; aOp[2].p4.z = "ok"; + aOp[5].p4type = P4_STATIC; + aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT); } + sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2); } } break; @@ -115127,7 +116245,8 @@ SQLITE_PRIVATE void sqlite3Pragma( ** 0x0008 (Not yet implemented) Create indexes that might have ** been helpful to recent queries ** - ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all ** of the optimizations listed above except Debug Mode, including new + ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all + ** of the optimizations listed above except Debug Mode, including new ** optimizations that have not yet been invented. If new optimizations are ** ever added that should be off by default, those off-by-default ** optimizations will have bitmasks of 0x10000 or larger. @@ -115289,7 +116408,6 @@ SQLITE_PRIVATE void sqlite3Pragma( zState = azLockName[j]; } sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } break; } @@ -115555,10 +116673,14 @@ static int pragmaVtabFilter( pragmaVtabCursorClear(pCsr); j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1; for(i=0; i<argc; i++, j++){ + const char *zText = (const char*)sqlite3_value_text(argv[i]); assert( j<ArraySize(pCsr->azArg) ); - pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i])); - if( pCsr->azArg[j]==0 ){ - return SQLITE_NOMEM; + assert( pCsr->azArg[j]==0 ); + if( zText ){ + pCsr->azArg[j] = sqlite3_mprintf("%s", zText); + if( pCsr->azArg[j]==0 ){ + return SQLITE_NOMEM; + } } } sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); @@ -115691,7 +116813,7 @@ static void corruptSchema( const char *zExtra /* Error information */ ){ sqlite3 *db = pData->db; - if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){ + if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){ char *z; if( zObj==0 ) zObj = "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); @@ -115751,7 +116873,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = saved_iDb; - assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); + assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); @@ -115816,6 +116938,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ assert( sqlite3_mutex_held(db->mutex) ); assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + db->init.busy = 1; + /* Construct the in-memory representation schema tables (sqlite_master or ** sqlite_temp_master) by invoking the parser directly. The appropriate ** table name will be inserted automatically by the parser so we can just @@ -115824,7 +116948,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ azArg[0] = zMasterName = SCHEMA_TABLE(iDb); azArg[1] = "1"; azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text," - "rootpage integer,sql text)"; + "rootpage int,sql text)"; azArg[3] = 0; initData.db = db; initData.iDb = iDb; @@ -115840,10 +116964,10 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ */ pDb = &db->aDb[iDb]; if( pDb->pBt==0 ){ - if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){ - DbSetProperty(db, 1, DB_SchemaLoaded); - } - return SQLITE_OK; + assert( iDb==1 ); + DbSetProperty(db, 1, DB_SchemaLoaded); + rc = SQLITE_OK; + goto error_out; } /* If there is not already a read-only (or read-write) transaction opened @@ -115978,8 +117102,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); } - if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ - /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider + if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){ + /* Black magic: If the SQLITE_WriteSchema flag is set, then consider ** the schema loaded, even if errors occurred. In this situation the ** current sqlite3_prepare() operation will fail, but the following one ** will attempt to compile the supplied statement against whatever subset @@ -116002,9 +117126,13 @@ initone_error_out: sqlite3BtreeLeave(pDb->pBt); error_out: - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); + if( rc ){ + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + } + sqlite3ResetOneSchema(db, iDb); } + db->init.busy = 0; return rc; } @@ -116020,42 +117148,29 @@ error_out: */ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ int i, rc; - int commit_internal = !(db->flags&SQLITE_InternChanges); + int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange); assert( sqlite3_mutex_held(db->mutex) ); assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); assert( db->init.busy==0 ); - rc = SQLITE_OK; - db->init.busy = 1; ENC(db) = SCHEMA_ENC(db); - for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ - if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; - rc = sqlite3InitOne(db, i, pzErrMsg); - if( rc ){ - sqlite3ResetOneSchema(db, i); - } + assert( db->nDb>0 ); + /* Do the main schema first */ + if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){ + rc = sqlite3InitOne(db, 0, pzErrMsg); + if( rc ) return rc; } - - /* Once all the other databases have been initialized, load the schema - ** for the TEMP database. This is loaded last, as the TEMP database - ** schema may contain references to objects in other databases. - */ -#ifndef SQLITE_OMIT_TEMPDB - assert( db->nDb>1 ); - if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, 1, pzErrMsg); - if( rc ){ - sqlite3ResetOneSchema(db, 1); + /* All other schemas after the main schema. The "temp" schema must be last */ + for(i=db->nDb-1; i>0; i--){ + if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ + rc = sqlite3InitOne(db, i, pzErrMsg); + if( rc ) return rc; } } -#endif - - db->init.busy = 0; - if( rc==SQLITE_OK && commit_internal ){ + if( commit_internal ){ sqlite3CommitInternalChanges(db); } - - return rc; + return SQLITE_OK; } /* @@ -116160,16 +117275,14 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ ** Free all memory allocations in the pParse object */ SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ - if( pParse ){ - sqlite3 *db = pParse->db; - sqlite3DbFree(db, pParse->aLabel); - sqlite3ExprListDelete(db, pParse->pConstExpr); - if( db ){ - assert( db->lookaside.bDisable >= pParse->disableLookaside ); - db->lookaside.bDisable -= pParse->disableLookaside; - } - pParse->disableLookaside = 0; + sqlite3 *db = pParse->db; + sqlite3DbFree(db, pParse->aLabel); + sqlite3ExprListDelete(db, pParse->pConstExpr); + if( db ){ + assert( db->lookaside.bDisable >= pParse->disableLookaside ); + db->lookaside.bDisable -= pParse->disableLookaside; } + pParse->disableLookaside = 0; } /* @@ -116179,7 +117292,7 @@ static int sqlite3Prepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ - int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ + u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ Vdbe *pReprepare, /* VM being reprepared */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ @@ -116196,6 +117309,14 @@ static int sqlite3Prepare( /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ assert( sqlite3_mutex_held(db->mutex) ); + /* For a long-term use prepared statement avoid the use of + ** lookaside memory. + */ + if( prepFlags & SQLITE_PREPARE_PERSISTENT ){ + sParse.disableLookaside++; + db->lookaside.bDisable++; + } + /* Check to verify that it is possible to get a read lock on all ** database schemas. The inability to get a read lock indicates that ** some other database connection is holding a write-lock, which in @@ -116227,7 +117348,7 @@ static int sqlite3Prepare( if( rc ){ const char *zDb = db->aDb[i].zDbSName; sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); - testcase( db->flags & SQLITE_ReadUncommitted ); + testcase( db->flags & SQLITE_ReadUncommit ); goto end_prepare; } } @@ -116295,8 +117416,7 @@ static int sqlite3Prepare( #endif if( db->init.busy==0 ){ - Vdbe *pVdbe = sParse.pVdbe; - sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); + sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags); } if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(sParse.pVdbe); @@ -116330,7 +117450,7 @@ static int sqlite3LockAndPrepare( sqlite3 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ - int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ + u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ Vdbe *pOld, /* VM being reprepared */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ @@ -116346,10 +117466,11 @@ static int sqlite3LockAndPrepare( } sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); - rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); + rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); if( rc==SQLITE_SCHEMA ){ + sqlite3ResetOneSchema(db, -1); sqlite3_finalize(*ppStmt); - rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail); + rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); @@ -116370,13 +117491,15 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){ sqlite3_stmt *pNew; const char *zSql; sqlite3 *db; + u8 prepFlags; assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) ); zSql = sqlite3_sql((sqlite3_stmt *)p); assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */ db = sqlite3VdbeDb(p); assert( sqlite3_mutex_held(db->mutex) ); - rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0); + prepFlags = sqlite3VdbePrepareFlags(p); + rc = sqlite3LockAndPrepare(db, zSql, -1, prepFlags, p, &pNew, 0); if( rc ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); @@ -116422,8 +117545,36 @@ SQLITE_API int sqlite3_prepare_v2( const char **pzTail /* OUT: End of parsed string */ ){ int rc; - rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail); - assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ + /* EVIDENCE-OF: R-37923-12173 The sqlite3_prepare_v2() interface works + ** exactly the same as sqlite3_prepare_v3() with a zero prepFlags + ** parameter. + ** + ** Proof in that the 5th parameter to sqlite3LockAndPrepare is 0 */ + rc = sqlite3LockAndPrepare(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,0, + ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); + return rc; +} +SQLITE_API int sqlite3_prepare_v3( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + int rc; + /* EVIDENCE-OF: R-56861-42673 sqlite3_prepare_v3() differs from + ** sqlite3_prepare_v2() only in having the extra prepFlags parameter, + ** which is a bit array consisting of zero or more of the + ** SQLITE_PREPARE_* flags. + ** + ** Proof by comparison to the implementation of sqlite3_prepare_v2() + ** directly above. */ + rc = sqlite3LockAndPrepare(db,zSql,nBytes, + SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), + 0,ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); return rc; } @@ -116436,7 +117587,7 @@ static int sqlite3Prepare16( sqlite3 *db, /* Database handle. */ const void *zSql, /* UTF-16 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ - int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */ + u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const void **pzTail /* OUT: End of parsed string */ ){ @@ -116464,7 +117615,7 @@ static int sqlite3Prepare16( sqlite3_mutex_enter(db->mutex); zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE); if( zSql8 ){ - rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8); + rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8); } if( zTail8 && pzTail ){ @@ -116510,7 +117661,22 @@ SQLITE_API int sqlite3_prepare16_v2( const void **pzTail /* OUT: End of parsed string */ ){ int rc; - rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail); + rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail); + assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ + return rc; +} +SQLITE_API int sqlite3_prepare16_v3( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-16 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + int rc; + rc = sqlite3Prepare16(db,zSql,nBytes, + SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK), + ppStmt,pzTail); assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } @@ -116596,7 +117762,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){ sqlite3ExprListDelete(db, p->pOrderBy); sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pOffset); - if( p->pWith ) sqlite3WithDelete(db, p->pWith); + if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; @@ -116639,7 +117805,8 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew = &standin; } if( pEList==0 ){ - pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0)); + pEList = sqlite3ExprListAppend(pParse, 0, + sqlite3Expr(pParse->db,TK_ASTERISK,0)); } pNew->pEList = pEList; pNew->op = TK_SELECT; @@ -116663,7 +117830,8 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->pLimit = pLimit; pNew->pOffset = pOffset; pNew->pWith = 0; - assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 ); + assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 + || pParse->db->mallocFailed!=0 ); if( pParse->db->mallocFailed ) { clearSelect(pParse->db, pNew, pNew!=&standin); pNew = 0; @@ -116690,7 +117858,7 @@ SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){ ** Delete the given Select structure and all of its substructures. */ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){ - if( p ) clearSelect(db, p, 1); + if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1); } /* @@ -116931,11 +118099,10 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ pLeft = &pSrc->a[0]; pRight = &pLeft[1]; for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){ - Table *pLeftTab = pLeft->pTab; Table *pRightTab = pRight->pTab; int isOuter; - if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; + if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; isOuter = (pRight->fg.jointype & JT_OUTER)!=0; /* When the NATURAL keyword is present, add WHERE clause terms for @@ -117083,11 +118250,11 @@ static void pushOntoSorter( if( pParse->db->mallocFailed ) return; pOp->p2 = nKey + nData; pKI = pOp->p4.pKeyInfo; - memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ + memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); - testcase( pKI->nXField>2 ); + testcase( pKI->nAllField > pKI->nKeyField+2 ); pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, - pKI->nXField-1); + pKI->nAllField-pKI->nKeyField-1); addrJmp = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); pSort->labelBkOut = sqlite3VdbeMakeLabel(v); @@ -117185,16 +118352,15 @@ static void codeDistinct( ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** -** If srcTab is negative, then the pEList expressions +** If srcTab is negative, then the p->pEList expressions ** are evaluated in order to get the data for this row. If srcTab is -** zero or more, then data is pulled from srcTab and pEList is used only +** zero or more, then data is pulled from srcTab and p->pEList is used only ** to get the number of columns and the collation sequence for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ - ExprList *pEList, /* List of values being extracted */ - int srcTab, /* Pull data from this table */ + int srcTab, /* Pull data from this table if non-negative */ SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */ DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */ SelectDest *pDest, /* How to dispose of the results */ @@ -117218,7 +118384,7 @@ static void selectInnerLoop( int regOrig; /* Start of memory holding full result (or 0) */ assert( v ); - assert( pEList!=0 ); + assert( p->pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; if( pSort && pSort->pOrderBy==0 ) pSort = 0; if( pSort==0 && !hasDistinct ){ @@ -117228,7 +118394,7 @@ static void selectInnerLoop( /* Pull the requested columns. */ - nResultCol = pEList->nExpr; + nResultCol = p->pEList->nExpr; if( pDest->iSdst==0 ){ if( pSort ){ @@ -117251,7 +118417,7 @@ static void selectInnerLoop( if( srcTab>=0 ){ for(i=0; i<nResultCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); - VdbeComment((v, "%s", pEList->a[i].zName)); + VdbeComment((v, "%s", p->pEList->a[i].zName)); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual @@ -117264,24 +118430,25 @@ static void selectInnerLoop( ecelFlags = 0; } if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){ - /* For each expression in pEList that is a copy of an expression in + /* For each expression in p->pEList that is a copy of an expression in ** the ORDER BY clause (pSort->pOrderBy), set the associated ** iOrderByCol value to one more than the index of the ORDER BY ** expression within the sort-key that pushOntoSorter() will generate. - ** This allows the pEList field to be omitted from the sorted record, + ** This allows the p->pEList field to be omitted from the sorted record, ** saving space and CPU cycles. */ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){ int j; if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ - pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; + p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; } } regOrig = 0; assert( eDest==SRT_Set || eDest==SRT_Mem || eDest==SRT_Coroutine || eDest==SRT_Output ); } - nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags); + nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult, + 0,ecelFlags); } /* If the DISTINCT keyword was present on the SELECT statement @@ -117313,7 +118480,7 @@ static void selectInnerLoop( iJump = sqlite3VdbeCurrentAddr(v) + nResultCol; for(i=0; i<nResultCol; i++){ - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr); + CollSeq *pColl = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr); if( i<nResultCol-1 ){ sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i); VdbeCoverage(v); @@ -117552,12 +118719,12 @@ static void selectInnerLoop( ** X extra columns. */ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ - int nExtra = (N+X)*(sizeof(CollSeq*)+1); + int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*); KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); if( p ){ p->aSortOrder = (u8*)&p->aColl[N+X]; - p->nField = (u16)N; - p->nXField = (u16)X; + p->nKeyField = (u16)N; + p->nAllField = (u16)(N+X); p->enc = ENC(db); p->db = db; p->nRef = 1; @@ -117631,10 +118798,7 @@ static KeyInfo *keyInfoFromExprList( if( pInfo ){ assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ - CollSeq *pColl; - pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); - if( !pColl ) pColl = db->pDfltColl; - pInfo->aColl[i-iStart] = pColl; + pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); pInfo->aSortOrder[i-iStart] = pItem->sortOrder; } } @@ -117884,23 +119048,23 @@ static void generateSortTail( ** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used. */ #ifdef SQLITE_ENABLE_COLUMN_METADATA -# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) +# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E) #else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ -# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) +# define columnType(A,B,C,D,E) columnTypeImpl(A,B) #endif static const char *columnTypeImpl( NameContext *pNC, +#ifndef SQLITE_ENABLE_COLUMN_METADATA + Expr *pExpr +#else Expr *pExpr, -#ifdef SQLITE_ENABLE_COLUMN_METADATA const char **pzOrigDb, const char **pzOrigTab, - const char **pzOrigCol, + const char **pzOrigCol #endif - u8 *pEstWidth ){ char const *zType = 0; int j; - u8 estWidth = 1; #ifdef SQLITE_ENABLE_COLUMN_METADATA char const *zOrigDb = 0; char const *zOrigTab = 0; @@ -117959,46 +119123,42 @@ static const char *columnTypeImpl( ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ - if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){ + if( iCol>=0 && iCol<pS->pEList->nExpr ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. - ** - ** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been - ** caught already by name resolution. */ NameContext sNC; Expr *p = pS->pEList->a[iCol].pExpr; sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; - zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth); + zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol); } - }else if( pTab->pSchema ){ - /* A real table */ + }else{ + /* A real table or a CTE table */ assert( !pS ); - if( iCol<0 ) iCol = pTab->iPKey; - assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); #ifdef SQLITE_ENABLE_COLUMN_METADATA + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; zOrigCol = "rowid"; }else{ zOrigCol = pTab->aCol[iCol].zName; zType = sqlite3ColumnType(&pTab->aCol[iCol],0); - estWidth = pTab->aCol[iCol].szEst; } zOrigTab = pTab->zName; - if( pNC->pParse ){ + if( pNC->pParse && pTab->pSchema ){ int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName; } #else + assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ zType = "INTEGER"; }else{ zType = sqlite3ColumnType(&pTab->aCol[iCol],0); - estWidth = pTab->aCol[iCol].szEst; } #endif } @@ -118017,7 +119177,7 @@ static const char *columnTypeImpl( sNC.pSrcList = pS->pSrc; sNC.pNext = pNC; sNC.pParse = pNC->pParse; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth); + zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); break; } #endif @@ -118031,7 +119191,6 @@ static const char *columnTypeImpl( *pzOrigCol = zOrigCol; } #endif - if( pEstWidth ) *pEstWidth = estWidth; return zType; } @@ -118058,7 +119217,7 @@ static void generateColumnTypes( const char *zOrigDb = 0; const char *zOrigTab = 0; const char *zOrigCol = 0; - zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0); + zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); /* The vdbe must make its own copy of the column-type and other ** column specific strings, in case the schema is reset before this @@ -118068,41 +119227,56 @@ static void generateColumnTypes( sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); #else - zType = columnType(&sNC, p, 0, 0, 0, 0); + zType = columnType(&sNC, p, 0, 0, 0); #endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } #endif /* !defined(SQLITE_OMIT_DECLTYPE) */ } -/* -** Return the Table objecct in the SrcList that has cursor iCursor. -** Or return NULL if no such Table object exists in the SrcList. -*/ -static Table *tableWithCursor(SrcList *pList, int iCursor){ - int j; - for(j=0; j<pList->nSrc; j++){ - if( pList->a[j].iCursor==iCursor ) return pList->a[j].pTab; - } - return 0; -} - /* -** Generate code that will tell the VDBE the names of columns -** in the result set. This information is used to provide the -** azCol[] values in the callback. +** Compute the column names for a SELECT statement. +** +** The only guarantee that SQLite makes about column names is that if the +** column has an AS clause assigning it a name, that will be the name used. +** That is the only documented guarantee. However, countless applications +** developed over the years have made baseless assumptions about column names +** and will break if those assumptions changes. Hence, use extreme caution +** when modifying this routine to avoid breaking legacy. +** +** See Also: sqlite3ColumnsFromExprList() +** +** The PRAGMA short_column_names and PRAGMA full_column_names settings are +** deprecated. The default setting is short=ON, full=OFF. 99.9% of all +** applications should operate this way. Nevertheless, we need to support the +** other modes for legacy: +** +** short=OFF, full=OFF: Column name is the text of the expression has it +** originally appears in the SELECT statement. In +** other words, the zSpan of the result expression. +** +** short=ON, full=OFF: (This is the default setting). If the result +** refers directly to a table column, then the +** result column name is just the table column +** name: COLUMN. Otherwise use zSpan. +** +** full=ON, short=ANY: If the result refers directly to a table column, +** then the result column name with the table name +** prefix, ex: TABLE.COLUMN. Otherwise use zSpan. */ static void generateColumnNames( Parse *pParse, /* Parser context */ - SrcList *pTabList, /* List of tables */ - ExprList *pEList /* Expressions defining the result set */ + Select *pSelect /* Generate column names for this SELECT statement */ ){ Vdbe *v = pParse->pVdbe; int i; Table *pTab; + SrcList *pTabList; + ExprList *pEList; sqlite3 *db = pParse->db; - int fullNames, shortNames; + 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 */ @@ -118112,24 +119286,31 @@ static void generateColumnNames( #endif if( pParse->colNamesSet || db->mallocFailed ) return; + /* Column names are determined by the left-most term of a compound select */ + while( pSelect->pPrior ) pSelect = pSelect->pPrior; + pTabList = pSelect->pSrc; + pEList = pSelect->pEList; assert( v!=0 ); assert( pTabList!=0 ); pParse->colNamesSet = 1; - fullNames = (db->flags & SQLITE_FullColNames)!=0; - shortNames = (db->flags & SQLITE_ShortColNames)!=0; + fullName = (db->flags & SQLITE_FullColNames)!=0; + srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName; sqlite3VdbeSetNumCols(v, pEList->nExpr); for(i=0; i<pEList->nExpr; i++){ - Expr *p; - p = pEList->a[i].pExpr; - if( NEVER(p==0) ) continue; + Expr *p = pEList->a[i].pExpr; + + assert( p!=0 ); + assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ + assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */ if( pEList->a[i].zName ){ + /* An AS clause always takes first priority */ char *zName = pEList->a[i].zName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); - }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) - && (pTab = tableWithCursor(pTabList, p->iTable))!=0 - ){ + }else if( srcName && p->op==TK_COLUMN ){ char *zCol; int iCol = p->iColumn; + pTab = p->pTab; + assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); if( iCol<0 ){ @@ -118137,10 +119318,7 @@ static void generateColumnNames( }else{ zCol = pTab->aCol[iCol].zName; } - if( !shortNames && !fullNames ){ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, - sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC); - }else if( fullNames ){ + if( fullName ){ char *zName = 0; zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol); sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); @@ -118168,6 +119346,15 @@ static void generateColumnNames( ** ** Return SQLITE_OK on success. If a memory allocation error occurs, ** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. +** +** The only guarantee that SQLite makes about column names is that if the +** column has an AS clause assigning it a name, that will be the name used. +** That is the only documented guarantee. However, countless applications +** developed over the years have made baseless assumptions about column names +** and will break if those assumptions changes. Hence, use extreme caution +** when modifying this routine to avoid breaking legacy. +** +** See Also: generateColumnNames() */ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( Parse *pParse, /* Parsing context */ @@ -118180,7 +119367,6 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( u32 cnt; /* Index added to make the name unique */ Column *aCol, *pCol; /* For looping over result columns */ int nCol; /* Number of columns in the result set */ - Expr *p; /* Expression for a single result column */ char *zName; /* Column name */ int nName; /* Size of name in zName[] */ Hash ht; /* Hash table of column names */ @@ -118190,6 +119376,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( nCol = pEList->nExpr; aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); testcase( aCol==0 ); + if( nCol>32767 ) nCol = 32767; }else{ nCol = 0; aCol = 0; @@ -118201,20 +119388,20 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){ /* Get an appropriate name for the column */ - p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ }else{ - Expr *pColExpr = p; /* The expression that is the result column name */ - Table *pTab; /* Table associated with this expression */ + Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr); while( pColExpr->op==TK_DOT ){ pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } - if( pColExpr->op==TK_COLUMN && pColExpr->pTab!=0 ){ + if( (pColExpr->op==TK_COLUMN || pColExpr->op==TK_AGG_COLUMN) + && pColExpr->pTab!=0 + ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; - pTab = pColExpr->pTab; + Table *pTab = pColExpr->pTab; if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; }else if( pColExpr->op==TK_ID ){ @@ -118225,7 +119412,11 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( zName = pEList->a[i].zSpan; } } - zName = sqlite3MPrintf(db, "%s", zName); + if( zName ){ + zName = sqlite3DbStrDup(db, zName); + }else{ + zName = sqlite3MPrintf(db,"column%d",i+1); + } /* Make sure the column name is unique. If the name is not unique, ** append an integer to the name so that it becomes unique. @@ -118282,7 +119473,6 @@ SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation( int i; Expr *p; struct ExprList_item *a; - u64 szAll = 0; assert( pSelect!=0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 ); @@ -118295,10 +119485,11 @@ SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation( const char *zType; int n, m; p = a[i].pExpr; - zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); - szAll += pCol->szEst; + zType = columnType(&sNC, p, 0, 0, 0); + /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); - if( zType && (m = sqlite3Strlen30(zType))>0 ){ + if( zType ){ + m = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zName); pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2); if( pCol->zName ){ @@ -118312,7 +119503,7 @@ SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation( pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } - pTab->szTabRow = sqlite3LogEst(szAll*4); + pTab->szTabRow = 1; /* Any non-zero value works */ } /* @@ -118355,19 +119546,16 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ ** Get a VDBE for the given parser context. Create a new one if necessary. ** If an error occurs, return NULL and leave a message in pParse. */ -static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){ - Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse); - if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1); +SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ + if( pParse->pVdbe ){ + return pParse->pVdbe; + } if( pParse->pToplevel==0 && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst) ){ pParse->okConstFactor = 1; } - return v; -} -SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse *pParse){ - Vdbe *v = pParse->pVdbe; - return v ? v : allocVdbe(pParse); + return sqlite3VdbeCreate(pParse); } @@ -118640,7 +119828,7 @@ static void generateWithRecursiveQuery( /* Output the single row in Current */ addrCont = sqlite3VdbeMakeLabel(v); codeOffset(v, regOffset, addrCont); - selectInnerLoop(pParse, p, p->pEList, iCurrent, + selectInnerLoop(pParse, p, iCurrent, 0, 0, pDest, addrCont, addrBreak); if( regLimit ){ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); @@ -118778,15 +119966,9 @@ static int multiSelect( db = pParse->db; pPrior = p->pPrior; dest = *pDest; - if( pPrior->pOrderBy ){ - sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", - selectOpName(p->op)); - rc = 1; - goto multi_select_end; - } - if( pPrior->pLimit ){ - sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", - selectOpName(p->op)); + if( pPrior->pOrderBy || pPrior->pLimit ){ + sqlite3ErrorMsg(pParse,"%s clause should come after %s not before", + pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op)); rc = 1; goto multi_select_end; } @@ -118954,17 +120136,12 @@ static int multiSelect( if( dest.eDest!=priorOp ){ int iCont, iBreak, iStart; assert( p->pEList ); - if( dest.eDest==SRT_Output ){ - Select *pFirst = p; - while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); - } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); iStart = sqlite3VdbeCurrentAddr(v); - selectInnerLoop(pParse, p, p->pEList, unionTab, + selectInnerLoop(pParse, p, unionTab, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); @@ -119029,11 +120206,6 @@ static int multiSelect( ** tables. */ assert( p->pEList ); - if( dest.eDest==SRT_Output ){ - Select *pFirst = p; - while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); - } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); @@ -119042,7 +120214,7 @@ static int multiSelect( iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); - selectInnerLoop(pParse, p, p->pEList, tab1, + selectInnerLoop(pParse, p, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); @@ -119641,14 +120813,6 @@ static int multiSelectOrderBy( */ sqlite3VdbeResolveLabel(v, labelEnd); - /* Set the number of output columns - */ - if( pDest->eDest==SRT_Output ){ - Select *pFirst = pPrior; - while( pFirst->pPrior ) pFirst = pFirst->pPrior; - generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); - } - /* Reassembly the compound query so that it will be freed correctly ** by the calling function */ if( p->pPrior ){ @@ -119702,7 +120866,9 @@ static Expr *substExpr( Expr *pExpr /* Expr in which substitution occurs */ ){ if( pExpr==0 ) return 0; - if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){ + if( ExprHasProperty(pExpr, EP_FromJoin) + && pExpr->iRightJoinTable==pSubst->iTable + ){ pExpr->iRightJoinTable = pSubst->iNewTable; } if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){ @@ -119726,9 +120892,12 @@ static Expr *substExpr( pCopy = &ifNullRow; } pNew = sqlite3ExprDup(db, pCopy, 0); - if( pNew && (pExpr->flags & EP_FromJoin) ){ + if( pNew && pSubst->isLeftJoin ){ + ExprSetProperty(pNew, EP_CanBeNull); + } + if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){ pNew->iRightJoinTable = pExpr->iRightJoinTable; - pNew->flags |= EP_FromJoin; + ExprSetProperty(pNew, EP_FromJoin); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; @@ -119812,67 +120981,74 @@ static void substSelect( ** exist on the table t1, a complete scan of the data might be ** avoided. ** -** Flattening is only attempted if all of the following are true: +** Flattening is subject to the following constraints: ** -** (1) The subquery and the outer query do not both use aggregates. +** (**) We no longer attempt to flatten aggregate subqueries. Was: +** The subquery and the outer query cannot both be aggregates. ** -** (2) The subquery is not an aggregate or (2a) the outer query is not a join -** and (2b) the outer query does not use subqueries other than the one -** FROM-clause subquery that is a candidate for flattening. (2b is -** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) +** (**) We no longer attempt to flatten aggregate subqueries. Was: +** (2) If the subquery is an aggregate then +** (2a) the outer query must not be a join and +** (2b) the outer query must not use subqueries +** other than the one FROM-clause subquery that is a candidate +** for flattening. (This is due to ticket [2f7170d73bf9abf80] +** from 2015-02-09.) ** -** (3) The subquery is not the right operand of a LEFT JOIN -** or the subquery is not itself a join and the outer query is not -** an aggregate. +** (3) If the subquery is the right operand of a LEFT JOIN then +** (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. ** -** (4) The subquery is not DISTINCT. +** (4) The subquery can not be DISTINCT. ** ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT ** sub-queries that were excluded from this optimization. Restriction ** (4) has since been expanded to exclude all DISTINCT subqueries. ** -** (6) The subquery does not use aggregates or the outer query is not -** DISTINCT. +** (**) We no longer attempt to flatten aggregate subqueries. Was: +** If the subquery is aggregate, the outer query may not be DISTINCT. ** -** (7) The subquery has a FROM clause. TODO: For subqueries without +** (7) The subquery must have a FROM clause. TODO: For subqueries without ** A FROM clause, consider adding a FROM clause with the special ** table sqlite_once that consists of a single row containing a ** single NULL. ** -** (8) The subquery does not use LIMIT or the outer query is not a join. +** (8) If the subquery uses LIMIT then the outer query may not be a join. ** -** (9) The subquery does not use LIMIT or the outer query does not use -** aggregates. +** (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 -** text: "The subquery does not use aggregates or the outer query -** does not use LIMIT." +** constraint: "If the subquery is aggregate then the outer query +** may not use LIMIT." ** -** (11) The subquery and the outer query do not both have ORDER BY clauses. +** (11) The subquery and the outer query may not both have ORDER BY clauses. ** ** (**) Not implemented. Subsumed into restriction (3). Was previously ** a separate restriction deriving from ticket #350. ** -** (13) The subquery and outer query do not both use LIMIT. +** (13) The subquery and outer query may not both use LIMIT. ** -** (14) The subquery does not use OFFSET. +** (14) The subquery may not use OFFSET. ** -** (15) The outer query is not part of a compound select or the -** subquery does not have a LIMIT clause. +** (15) If the outer query is part of a compound select, then the +** subquery may not use LIMIT. ** (See ticket #2339 and ticket [02a8e81d44]). ** -** (16) The outer query is not an aggregate or the subquery does -** not contain ORDER BY. (Ticket #2942) This used to not matter +** (16) If the outer query is aggregate, then the subquery may not +** use ORDER BY. (Ticket #2942) This used to not matter ** until we introduced the group_concat() function. ** -** (17) The sub-query is not a compound select, or it is a UNION ALL -** compound clause made up entirely of non-aggregate queries, and -** the parent query: -** -** * is not itself part of a compound select, -** * is not an aggregate or DISTINCT query, and -** * is not a join +** (17) If the subquery is a compound select, then +** (17a) all compound operators must be a UNION ALL, and +** (17b) no terms within the subquery compound may be aggregate +** or DISTINCT, and +** (17c) every term within the subquery compound must have a FROM clause +** (17d) the outer query may not be +** (17d1) aggregate, or +** (17d2) DISTINCT, or +** (17d3) a join. ** ** The parent and sub-query may contain WHERE clauses. Subject to ** rules (11), (13) and (14), they may also contain ORDER BY, @@ -119888,29 +121064,32 @@ static void substSelect( ** syntax error and return a detailed message. ** ** (18) If the sub-query is a compound select, then all terms of the -** ORDER by clause of the parent must be simple references to +** ORDER BY clause of the parent must be simple references to ** columns of the sub-query. ** -** (19) The subquery does not use LIMIT or the outer query does not +** (19) If the subquery uses LIMIT then the outer query may not ** have a WHERE clause. ** -** (20) If the sub-query is a compound select, then it must not use -** an ORDER BY clause. Ticket #3773. We could relax this constraint -** somewhat by saying that the terms of the ORDER BY clause must -** appear as unmodified result columns in the outer query. But we -** have other optimizations in mind to deal with that case. +** (**) Subsumed into (17d3). Was: If the sub-query is a compound select, +** then it must not use an ORDER BY clause - Ticket #3773. Because +** of (17d3), then only way to have a compound subquery is if it is +** the only term in the FROM clause of the outer query. But if the +** only term in the FROM clause has an ORDER BY, then it will be +** implemented as a co-routine and the flattener will never be called. ** -** (21) The subquery does not use LIMIT or the outer query is not +** (21) If the subquery uses LIMIT then the outer query may not be ** DISTINCT. (See ticket [752e1646fc]). ** -** (22) The subquery is not a recursive CTE. +** (22) The subquery may not be a recursive CTE. ** -** (23) The parent is not a recursive CTE, or the sub-query is not a -** compound query. This restriction is because transforming the +** (**) Subsumed into restriction (17d3). Was: If the outer query is +** a recursive CTE, then the sub-query may not be a compound query. +** This restriction is because transforming the ** parent to a compound query confuses the code that handles ** recursive queries in multiSelect(). ** -** (24) The subquery is not an aggregate that uses the built-in min() or +** (**) We no longer attempt to flatten aggregate subqueries. Was: +** The subquery may not be an aggregate that uses the built-in min() or ** or max() functions. (Without this restriction, a query like: ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily ** return the value X for which Y was maximal.) @@ -119918,7 +121097,7 @@ static void substSelect( ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query -** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. +** uses aggregates. ** ** If flattening is not attempted, this routine is a no-op and returns 0. ** If flattening is attempted this routine returns 1. @@ -119930,8 +121109,7 @@ static int flattenSubquery( Parse *pParse, /* Parsing context */ Select *p, /* The parent or outer SELECT statement */ int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ - int isAgg, /* True if outer SELECT uses aggregate functions */ - int subqueryIsAgg /* True if the subquery uses aggregate functions */ + int isAgg /* True if outer SELECT uses aggregate functions */ ){ const char *zSavedAuthContext = pParse->zAuthContext; Select *pParent; /* Current UNION ALL term of the other query */ @@ -119939,7 +121117,6 @@ static int flattenSubquery( Select *pSub1; /* Pointer to the rightmost select in sub-query */ SrcList *pSrc; /* The FROM clause of the outer query */ SrcList *pSubSrc; /* The FROM clause of the subquery */ - ExprList *pList; /* The result set of the outer query */ int iParent; /* VDBE cursor number of the pSub result set temp table */ int iNewParent = -1;/* Replacement table for iParent */ int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ @@ -119951,7 +121128,7 @@ static int flattenSubquery( /* Check to see if flattening is permitted. Return 0 if not. */ assert( p!=0 ); - assert( p->pPrior==0 ); /* Unable to flatten compound queries */ + assert( p->pPrior==0 ); if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0; pSrc = p->pSrc; assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc ); @@ -119959,16 +121136,6 @@ static int flattenSubquery( iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( subqueryIsAgg ){ - if( isAgg ) return 0; /* Restriction (1) */ - if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ - if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) - || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 - || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 - ){ - return 0; /* Restriction (2b) */ - } - } pSubSrc = pSub->pSrc; assert( pSubSrc ); @@ -119983,13 +121150,10 @@ static int flattenSubquery( return 0; /* Restriction (15) */ } if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ - if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */ + if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */ if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){ return 0; /* Restrictions (8)(9) */ } - if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){ - return 0; /* Restriction (6) */ - } if( p->pOrderBy && pSub->pOrderBy ){ return 0; /* Restriction (11) */ } @@ -119998,18 +121162,14 @@ static int flattenSubquery( if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){ return 0; /* Restriction (21) */ } - testcase( pSub->selFlags & SF_Recursive ); - testcase( pSub->selFlags & SF_MinMaxAgg ); - if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){ - return 0; /* Restrictions (22) and (24) */ - } - if( (p->selFlags & SF_Recursive) && pSub->pPrior ){ - return 0; /* Restriction (23) */ + if( pSub->selFlags & (SF_Recursive) ){ + return 0; /* Restrictions (22) */ } /* ** If the subquery is the right operand of a LEFT JOIN, then the - ** subquery may not be a join itself. Example of why this is not allowed: + ** subquery may not be a join itself (3a). Example of why this is not + ** allowed: ** ** t1 LEFT OUTER JOIN (t2 JOIN t3) ** @@ -120020,54 +121180,53 @@ 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. This is an artifact of the way aggregates - ** are processed - there is not mechanism to determine if the LEFT JOIN - ** table should be all-NULL. + ** 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)!=0 ){ isLeftJoin = 1; - if( pSubSrc->nSrc>1 || isAgg ){ - return 0; /* Restriction (3) */ + if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){ + /* (3a) (3c) (3b) */ + return 0; } } #ifdef SQLITE_EXTRA_IFNULLROW else if( iFrom>0 && !isAgg ){ /* Setting isLeftJoin 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. */ + ** every reference to any result column from subquery in a join, even + ** though they are not necessary. This will stress-test the OP_IfNullRow + ** opcode. */ isLeftJoin = -1; } #endif - /* Restriction 17: If the sub-query is a compound SELECT, then it must + /* Restriction (17): If the sub-query is a compound SELECT, then it must ** use only the UNION ALL operator. And none of the simple select queries ** that make up the compound SELECT are allowed to be aggregate or distinct ** queries. */ if( pSub->pPrior ){ - if( pSub->pOrderBy ){ - return 0; /* Restriction 20 */ - } if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){ - return 0; + return 0; /* (17d1), (17d2), or (17d3) */ } for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); assert( pSub->pSrc!=0 ); assert( pSub->pEList->nExpr==pSub1->pEList->nExpr ); - if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 - || (pSub1->pPrior && pSub1->op!=TK_ALL) - || pSub1->pSrc->nSrc<1 + if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */ + || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */ + || pSub1->pSrc->nSrc<1 /* (17c) */ ){ return 0; } testcase( pSub1->pSrc->nSrc>1 ); } - /* Restriction 18. */ + /* Restriction (18). */ if( p->pOrderBy ){ int ii; for(ii=0; ii<p->pOrderBy->nExpr; ii++){ @@ -120076,6 +121235,23 @@ static int flattenSubquery( } } + /* Ex-restriction (23): + ** The only way that the recursive part of a CTE can contain a compound + ** subquery is for the subquery to be one term of a join. But if the + ** subquery is a join, then the flattening has already been stopped by + ** restriction (17d3) + */ + assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 ); + + /* Ex-restriction (20): + ** A compound subquery must be the only term in the FROM clause of the + ** outer query by restriction (17d3). But if that term also has an + ** ORDER BY clause, then the subquery will be implemented by co-routine + ** and so the flattener will never be invoked. Hence, it is not possible + ** for the subquery to be a compound and have an ORDER BY clause. + */ + assert( pSub->pPrior==0 || pSub->pOrderBy==0 ); + /***** If we reach this point, flattening is permitted. *****/ SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n", pSub->zSelName, pSub, iFrom)); @@ -120264,14 +121440,6 @@ static int flattenSubquery( ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ - pList = pParent->pEList; - for(i=0; i<pList->nExpr; i++){ - if( pList->a[i].zName==0 ){ - char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); - sqlite3Dequote(zName); - pList->a[i].zName = zName; - } - } if( pSub->pOrderBy ){ /* At this point, any non-zero iOrderByCol values indicate that the ** ORDER BY column expression is identical to the iOrderByCol'th @@ -120296,18 +121464,7 @@ static int flattenSubquery( if( isLeftJoin>0 ){ setJoinExpr(pWhere, iNewParent); } - if( subqueryIsAgg ){ - assert( pParent->pHaving==0 ); - pParent->pHaving = pParent->pWhere; - pParent->pWhere = pWhere; - pParent->pHaving = sqlite3ExprAnd(db, - sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving - ); - assert( pParent->pGroupBy==0 ); - pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); - }else{ - pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); - } + pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); if( db->mallocFailed==0 ){ SubstContext x; x.pParse = pParse; @@ -120370,9 +121527,13 @@ static int flattenSubquery( ** ** Do not attempt this optimization if: ** -** (1) The inner query is an aggregate. (In that case, we'd really want -** to copy the outer WHERE-clause terms onto the HAVING clause of the -** inner query. But they probably won't help there so do not bother.) +** (1) (** This restriction was removed on 2017-09-29. We used to +** disallow this optimization for aggregate subqueries, but now +** it is allowed by putting the extra terms on the HAVING clause. +** The added HAVING clause is pointless if the subquery lacks +** a GROUP BY clause. But such a HAVING clause is also harmless +** so there does not appear to be any reason to add extra logic +** to suppress it. **) ** ** (2) The inner query is the recursive part of a common table expression. ** @@ -120397,16 +121558,22 @@ static int pushDownWhereTerms( ){ Expr *pNew; int nChng = 0; - Select *pX; /* For looping over compound SELECTs in pSubq */ if( pWhere==0 ) return 0; - for(pX=pSubq; pX; pX=pX->pPrior){ - if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ - testcase( pX->selFlags & SF_Aggregate ); - testcase( pX->selFlags & SF_Recursive ); - testcase( pX!=pSubq ); - return 0; /* restrictions (1) and (2) */ + if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */ + +#ifdef SQLITE_DEBUG + /* Only the first term of a compound can have a WITH clause. But make + ** sure no other terms are marked SF_Recursive in case something changes + ** in the future. + */ + { + Select *pX; + for(pX=pSubq; pX; pX=pX->pPrior){ + assert( (pX->selFlags & (SF_Recursive))==0 ); } } +#endif + if( pSubq->pLimit!=0 ){ return 0; /* restriction (3) */ } @@ -120414,7 +121581,7 @@ static int pushDownWhereTerms( nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); pWhere = pWhere->pLeft; } - if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ + if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */ if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ nChng++; while( pSubq ){ @@ -120426,7 +121593,11 @@ static int pushDownWhereTerms( x.isLeftJoin = 0; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); - pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); + if( pSubq->selFlags & SF_Aggregate ){ + pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew); + }else{ + pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); + } pSubq = pSubq->pPrior; } } @@ -120754,7 +121925,8 @@ static int withExpand( ); return SQLITE_ERROR; } - assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); + assert( pTab->nTabRef==1 || + ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); pCte->zCteErr = "circular reference: %s"; pSavedWith = pParse->pWith; @@ -120811,7 +121983,7 @@ static int withExpand( */ static void selectPopWith(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; - if( pParse->pWith && p->pPrior==0 ){ + if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){ With *pWith = findRightmost(p)->pWith; if( pWith!=0 ){ assert( pParse->pWith==pWith ); @@ -120866,7 +122038,7 @@ static int selectExpander(Walker *pWalker, Select *p){ } pTabList = p->pSrc; pEList = p->pEList; - if( p->pWith ){ + if( OK_IF_ALWAYS_TRUE(p->pWith) ){ sqlite3WithPush(pParse, p->pWith, 0); } @@ -120898,7 +122070,11 @@ static int selectExpander(Walker *pWalker, Select *p){ pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nTabRef = 1; - pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); + if( pFrom->zAlias ){ + pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias); + }else{ + pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab); + } while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; @@ -121108,12 +122284,10 @@ static int selectExpander(Walker *pWalker, Select *p){ sqlite3ExprListDelete(db, pEList); p->pEList = pNew; } -#if SQLITE_MAX_COLUMN if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); return WRC_Abort; } -#endif return WRC_Continue; } @@ -121132,6 +122306,25 @@ SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ } /* +** No-op routine for the parse-tree walker for SELECT statements. +** subquery in the parser tree. +*/ +SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + return WRC_Continue; +} + +#if SQLITE_DEBUG +/* +** Always assert. This xSelectCallback2 implementation proves that the +** xSelectCallback2 is never invoked. +*/ +SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); + assert( 0 ); +} +#endif +/* ** This routine "expands" a SELECT statement and all of its subqueries. ** For additional information on what it means to "expand" a SELECT ** statement, see the comment on the selectExpand worker callback above. @@ -121146,11 +122339,11 @@ SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; - memset(&w, 0, sizeof(w)); w.xExprCallback = sqlite3ExprWalkNoop; w.pParse = pParse; - if( pParse->hasCompound ){ + if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){ w.xSelectCallback = convertCompoundSelectToSubquery; + w.xSelectCallback2 = 0; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; @@ -121210,7 +122403,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; - memset(&w, 0, sizeof(w)); + w.xSelectCallback = sqlite3SelectWalkNoop; w.xSelectCallback2 = selectAddSubqueryTypeInfo; w.xExprCallback = sqlite3ExprWalkNoop; w.pParse = pParse; @@ -121236,15 +122429,13 @@ SQLITE_PRIVATE void sqlite3SelectPrep( Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* Name context for container */ ){ - sqlite3 *db; - if( NEVER(p==0) ) return; - db = pParse->db; - if( db->mallocFailed ) return; + assert( p!=0 || pParse->db->mallocFailed ); + if( pParse->db->mallocFailed ) return; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); - if( pParse->nErr || db->mallocFailed ) return; + if( pParse->nErr || pParse->db->mallocFailed ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); - if( pParse->nErr || db->mallocFailed ) return; + if( pParse->nErr || pParse->db->mallocFailed ) return; sqlite3SelectAddTypeInfo(pParse, p); } @@ -121504,7 +122695,9 @@ static struct SrcList_item *isSelfJoinView( if( pItem->zName==0 ) continue; if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue; if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue; - if( sqlite3ExprCompare(pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) ){ + if( sqlite3ExprCompare(0, + pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) + ){ /* The view was modified by some other optimization such as ** pushDownWhereTerms() */ continue; @@ -121514,6 +122707,88 @@ static struct SrcList_item *isSelfJoinView( return 0; } +#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION +/* +** Attempt to transform a query of the form +** +** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) +** +** Into this: +** +** SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2) +** +** The transformation only works if all of the following are true: +** +** * The subquery is a UNION ALL of two or more terms +** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries +** * The outer query is a simple count(*) +** +** Return TRUE if the optimization is undertaken. +*/ +static int countOfViewOptimization(Parse *pParse, Select *p){ + Select *pSub, *pPrior; + Expr *pExpr; + Expr *pCount; + sqlite3 *db; + if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ + if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ + pExpr = p->pEList->a[0].pExpr; + if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ + if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */ + if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ + if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */ + pSub = p->pSrc->a[0].pSelect; + if( pSub==0 ) return 0; /* The FROM is a subquery */ + if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */ + do{ + if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ + if( pSub->pWhere ) return 0; /* No WHERE clause */ + if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */ + pSub = pSub->pPrior; /* Repeat over compound */ + }while( pSub ); + + /* If we reach this point then it is OK to perform the transformation */ + + db = pParse->db; + pCount = pExpr; + pExpr = 0; + pSub = p->pSrc->a[0].pSelect; + p->pSrc->a[0].pSelect = 0; + sqlite3SrcListDelete(db, p->pSrc); + p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc)); + while( pSub ){ + Expr *pTerm; + pPrior = pSub->pPrior; + pSub->pPrior = 0; + pSub->pNext = 0; + pSub->selFlags |= SF_Aggregate; + pSub->selFlags &= ~SF_Compound; + pSub->nSelectRow = 0; + sqlite3ExprListDelete(db, pSub->pEList); + pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount; + pSub->pEList = sqlite3ExprListAppend(pParse, 0, pTerm); + pTerm = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, pTerm, pSub); + if( pExpr==0 ){ + pExpr = pTerm; + }else{ + pExpr = sqlite3PExpr(pParse, TK_PLUS, pTerm, pExpr); + } + pSub = pPrior; + } + p->pEList->a[0].pExpr = pExpr; + p->selFlags &= ~SF_Aggregate; + +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x400 ){ + SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + return 1; +} +#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */ + /* ** Generate code for the SELECT statement given in the p argument. ** @@ -121598,13 +122873,20 @@ SQLITE_PRIVATE int sqlite3Select( } #endif + /* Get a pointer the VDBE under construction, allocating a new VDBE if one + ** does not already exist */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto select_end; + if( pDest->eDest==SRT_Output ){ + generateColumnNames(pParse, p); + } + /* Try to flatten subqueries in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; Select *pSub = pItem->pSelect; - int isAggSub; Table *pTab = pItem->pTab; if( pSub==0 ) continue; @@ -121616,13 +122898,36 @@ SQLITE_PRIVATE int sqlite3Select( goto select_end; } - isAggSub = (pSub->selFlags & SF_Aggregate)!=0; - if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ + /* Do not try to flatten an aggregate subquery. + ** + ** Flattening an aggregate subquery is only possible if the outer query + ** is not a join. But if the outer query is not a join, then the subquery + ** will be implemented as a co-routine and there is no advantage to + ** flattening in that case. + */ + if( (pSub->selFlags & SF_Aggregate)!=0 ) continue; + assert( pSub->pGroupBy==0 ); + + /* If the subquery contains an ORDER BY clause and if + ** it will be implemented as a co-routine, then do not flatten. This + ** restriction allows SQL constructs like this: + ** + ** SELECT expensive_function(x) + ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10); + ** + ** The expensive_function() is only computed on the 10 rows that + ** are output, rather than every row of the table. + */ + if( pSub->pOrderBy!=0 + && i==0 + && (pTabList->nSrc==1 + || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) + ){ + continue; + } + + if( flattenSubquery(pParse, p, i, isAgg) ){ /* This subquery can be absorbed into its parent. */ - if( isAggSub ){ - isAgg = 1; - p->selFlags |= SF_Aggregate; - } i = -1; } pTabList = p->pSrc; @@ -121633,11 +122938,6 @@ SQLITE_PRIVATE int sqlite3Select( } #endif - /* Get a pointer the VDBE under construction, allocating a new VDBE if one - ** does not already exist */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) goto select_end; - #ifndef SQLITE_OMIT_COMPOUND_SELECT /* Handle compound SELECT statements using the separate multiSelect() ** procedure. @@ -121661,10 +122961,14 @@ SQLITE_PRIVATE int sqlite3Select( struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub; +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + const char *zSavedAuthContext; +#endif - /* Issue SQLITE_READ authorizations with a fake column name for any tables that - ** are referenced but from which no values are extracted. Examples of where these - ** kinds of null SQLITE_READ authorizations would occur: + /* Issue SQLITE_READ authorizations with a fake column name for any + ** tables that are referenced but from which no values are extracted. + ** Examples of where these kinds of null SQLITE_READ authorizations + ** would occur: ** ** SELECT count(*) FROM t1; -- SQLITE_READ t1."" ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2."" @@ -121672,10 +122976,10 @@ SQLITE_PRIVATE int sqlite3Select( ** The fake column name is an empty string. It is possible for a table to ** have a column named by the empty string, in which case there is no way to ** distinguish between an unreferenced table and an actual reference to the - ** "" column. The original design was for the fake column name to be a NULL, + ** "" column. The original design was for the fake column name to be a NULL, ** which would be unambiguous. But legacy authorization callbacks might - ** assume the column name is non-NULL and segfault. The use of an empty string - ** for the fake column name seems safer. + ** assume the column name is non-NULL and segfault. The use of an empty + ** string for the fake column name seems safer. */ if( pItem->colUsed==0 ){ sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase); @@ -121727,16 +123031,14 @@ SQLITE_PRIVATE int sqlite3Select( #endif } + zSavedAuthContext = pParse->zAuthContext; + pParse->zAuthContext = pItem->zName; + /* Generate code to implement the subquery ** - ** The subquery is implemented as a co-routine if all of these are true: - ** (1) The subquery is guaranteed to be the outer loop (so that it - ** does not need to be computed more than once) - ** (2) The ALL keyword after SELECT is omitted. (Applications are - ** allowed to say "SELECT ALL" instead of just "SELECT" to disable - ** the use of co-routines.) - ** (3) Co-routines are not disabled using sqlite3_test_control() - ** with SQLITE_TESTCTRL_OPTIMIZATIONS. + ** The subquery is implemented as a co-routine if the subquery is + ** guaranteed to be the outer loop (so that it does not need to be + ** computed more than once) ** ** TODO: Are there other reasons beside (1) to use a co-routine ** implementation? @@ -121744,13 +123046,12 @@ SQLITE_PRIVATE int sqlite3Select( if( i==0 && (pTabList->nSrc==1 || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ - && (p->selFlags & SF_All)==0 /* (2) */ - && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */ ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. */ int addrTop = sqlite3VdbeCurrentAddr(v)+1; + pItem->regReturn = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop); VdbeComment((v, "%s", pItem->pTab->zName)); @@ -121791,6 +123092,9 @@ SQLITE_PRIVATE int sqlite3Select( pPrior = isSelfJoinView(pTabList, pItem); if( pPrior ){ sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor); + explainSetInteger(pItem->iSelectId, pPrior->iSelectId); + assert( pPrior->pSelect!=0 ); + pSub->nSelectRow = pPrior->pSelect->nSelectRow; }else{ sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); @@ -121805,6 +123109,7 @@ SQLITE_PRIVATE int sqlite3Select( } if( db->mallocFailed ) goto select_end; pParse->nHeight -= sqlite3SelectExprHeight(p); + pParse->zAuthContext = zSavedAuthContext; #endif } @@ -121823,6 +123128,16 @@ SQLITE_PRIVATE int sqlite3Select( } #endif +#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION + if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) + && countOfViewOptimization(pParse, p) + ){ + if( db->mallocFailed ) goto select_end; + pEList = p->pEList; + pTabList = p->pSrc; + } +#endif + /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and ** if the select-list is the same as the ORDER BY list, then this query ** can be rewritten as a GROUP BY. In other words, this: @@ -121942,7 +123257,8 @@ SQLITE_PRIVATE int sqlite3Select( } /* Use the standard inner loop. */ - selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest, + assert( p->pEList==pEList ); + selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, sqlite3WhereContinueLabel(pWInfo), sqlite3WhereBreakLabel(pWInfo)); @@ -122245,7 +123561,7 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, &sAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, p->pEList, -1, &sSort, + selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, addrOutputRow+1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); @@ -122389,7 +123705,7 @@ SQLITE_PRIVATE int sqlite3Select( sSort.pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); - selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, + selectInnerLoop(pParse, p, -1, 0, 0, pDest, addrEnd, addrEnd); sqlite3ExprListDelete(db, pDel); } @@ -122424,12 +123740,6 @@ SQLITE_PRIVATE int sqlite3Select( select_end: explainSetInteger(pParse->iSelectId, iRestoreSelectId); - /* Identify column names if results of the SELECT are to be output. - */ - if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){ - generateColumnNames(pParse, pTabList, pEList); - } - sqlite3DbFree(db, sAggInfo.aCol); sqlite3DbFree(db, sAggInfo.aFunc); #if SELECTTRACE_ENABLED @@ -122950,6 +124260,7 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); + testcase( z==0 ); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zDbSName, MASTER_NAME, zName, @@ -123228,7 +124539,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const ch *pp = (*pp)->pNext; } sqlite3DeleteTrigger(db, pTrigger); - db->flags |= SQLITE_InternChanges; + db->mDbFlags |= DBFLAG_SchemaChange; } } @@ -124549,12 +125860,6 @@ static void updateVirtualTable( if( pWInfo==0 ) return; /* Populate the argument registers. */ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); - if( pRowid ){ - sqlite3ExprCode(pParse, pRowid, regArg+1); - }else{ - sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); - } for(i=0; i<pTab->nCol; i++){ if( aXRef[i]>=0 ){ sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i); @@ -124562,6 +125867,23 @@ static void updateVirtualTable( sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i); } } + if( HasRowid(pTab) ){ + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg); + if( pRowid ){ + sqlite3ExprCode(pParse, pRowid, regArg+1); + }else{ + sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1); + } + }else{ + Index *pPk; /* PRIMARY KEY index */ + i16 iPk; /* PRIMARY KEY column */ + pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk!=0 ); + assert( pPk->nKeyCol==1 ); + iPk = pPk->aiColumn[0]; + sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg); + sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); + } bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); @@ -124746,7 +126068,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; /* The temporary database we vacuum into */ - int saved_flags; /* Saved value of the db->flags */ + u16 saved_mDbFlags; /* Saved value of db->mDbFlags */ + u32 saved_flags; /* Saved value of db->flags */ int saved_nChange; /* Saved value of db->nChange */ int saved_nTotalChange; /* Saved value of db->nTotalChange */ u8 saved_mTrace; /* Saved trace settings */ @@ -124769,11 +126092,12 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; + saved_mDbFlags = db->mDbFlags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_mTrace = db->mTrace; - db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks - | SQLITE_PreferBuiltin | SQLITE_Vacuum); + db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; + db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); db->mTrace = 0; @@ -124817,7 +126141,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; char *zKey; - sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey); if( nKey ) db->nextPagesize = 0; } #endif @@ -124884,8 +126208,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ "WHERE type='table'AND coalesce(rootpage,1)>0", zDbMain ); - assert( (db->flags & SQLITE_Vacuum)!=0 ); - db->flags &= ~SQLITE_Vacuum; + assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 ); + db->mDbFlags &= ~DBFLAG_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy the triggers, views, and virtual tables from the main database @@ -124953,6 +126277,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){ end_of_vacuum: /* Restore the original value of db->flags */ db->init.iDb = 0; + db->mDbFlags = saved_mDbFlags; db->flags = saved_flags; db->nChange = saved_nChange; db->nTotalChange = saved_nTotalChange; @@ -125029,8 +126354,10 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule( ){ Module *pMod; int nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); - if( pMod ){ + pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); + if( pMod==0 ){ + sqlite3OomFault(db); + }else{ Module *pDel; char *zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); @@ -125505,13 +126832,14 @@ static int vtabCallConstructor( } } - zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); + zModuleName = sqlite3DbStrDup(db, pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM_BKPT; } - pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); + pVTable = sqlite3MallocZero(sizeof(VTable)); if( !pVTable ){ + sqlite3OomFault(db); sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM_BKPT; } @@ -125631,6 +126959,7 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); + pParse->rc = rc; } sqlite3DbFree(db, zErr); } @@ -125720,10 +127049,10 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, */ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; - Parse *pParse; int rc = SQLITE_OK; Table *pTab; char *zErr = 0; + Parse sParse; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ @@ -125740,55 +127069,55 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pTab = pCtx->pTab; assert( IsVirtual(pTab) ); - pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); - if( pParse==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - pParse->declareVtab = 1; - pParse->db = db; - pParse->nQueryLoop = 1; - - if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) - && pParse->pNewTable - && !db->mallocFailed - && !pParse->pNewTable->pSelect - && !IsVirtual(pParse->pNewTable) - ){ - if( !pTab->aCol ){ - Table *pNew = pParse->pNewTable; - Index *pIdx; - pTab->aCol = pNew->aCol; - pTab->nCol = pNew->nCol; - pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); - pNew->nCol = 0; - pNew->aCol = 0; - assert( pTab->pIndex==0 ); - if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){ - rc = SQLITE_ERROR; - } - pIdx = pNew->pIndex; - if( pIdx ){ - assert( pIdx->pNext==0 ); - pTab->pIndex = pIdx; - pNew->pIndex = 0; - pIdx->pTable = pTab; - } + memset(&sParse, 0, sizeof(sParse)); + sParse.declareVtab = 1; + sParse.db = db; + sParse.nQueryLoop = 1; + if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) + && sParse.pNewTable + && !db->mallocFailed + && !sParse.pNewTable->pSelect + && !IsVirtual(sParse.pNewTable) + ){ + if( !pTab->aCol ){ + Table *pNew = sParse.pNewTable; + Index *pIdx; + pTab->aCol = pNew->aCol; + pTab->nCol = pNew->nCol; + pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); + pNew->nCol = 0; + pNew->aCol = 0; + assert( pTab->pIndex==0 ); + assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 ); + if( !HasRowid(pNew) + && pCtx->pVTable->pMod->pModule->xUpdate!=0 + && sqlite3PrimaryKeyIndex(pNew)->nKeyCol!=1 + ){ + /* WITHOUT ROWID virtual tables must either be read-only (xUpdate==0) + ** or else must have a single-column PRIMARY KEY */ + rc = SQLITE_ERROR; + } + pIdx = pNew->pIndex; + if( pIdx ){ + assert( pIdx->pNext==0 ); + pTab->pIndex = pIdx; + pNew->pIndex = 0; + pIdx->pTable = pTab; } - pCtx->bDeclared = 1; - }else{ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); - sqlite3DbFree(db, zErr); - rc = SQLITE_ERROR; - } - pParse->declareVtab = 0; - - if( pParse->pVdbe ){ - sqlite3VdbeFinalize(pParse->pVdbe); } - sqlite3DeleteTable(db, pParse->pNewTable); - sqlite3ParserReset(pParse); - sqlite3StackFree(db, pParse); + pCtx->bDeclared = 1; + }else{ + sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); + sqlite3DbFree(db, zErr); + rc = SQLITE_ERROR; } + sParse.declareVtab = 0; + + if( sParse.pVdbe ){ + sqlite3VdbeFinalize(sParse.pVdbe); + } + sqlite3DeleteTable(db, sParse.pNewTable); + sqlite3ParserReset(&sParse); assert( (rc&0xff)==rc ); rc = sqlite3ApiExit(db, rc); @@ -126535,6 +127864,7 @@ struct WhereTerm { #define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ #define TERM_LIKE 0x400 /* The original LIKE operator */ #define TERM_IS 0x800 /* Term.pExpr is an IS operator */ +#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -126624,6 +127954,7 @@ struct WhereAndInfo { ** no gaps. */ struct WhereMaskSet { + int bVarSelect; /* Used by sqlite3WhereExprUsage() */ int n; /* Number of assigned cursor values */ int ix[BMS]; /* Cursor assigned to each bit */ }; @@ -126764,7 +128095,6 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC ** WO_LE == SQLITE_INDEX_CONSTRAINT_LE ** WO_GT == SQLITE_INDEX_CONSTRAINT_GT ** WO_GE == SQLITE_INDEX_CONSTRAINT_GE -** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH */ #define WO_IN 0x0001 #define WO_EQ 0x0002 @@ -126772,7 +128102,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) -#define WO_MATCH 0x0040 +#define WO_AUX 0x0040 /* Op useful to virtual tables only */ #define WO_IS 0x0080 #define WO_ISNULL 0x0100 #define WO_OR 0x0200 /* Two or more OR-connected terms */ @@ -127585,7 +128915,7 @@ static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){ pWalker->eCode = 1; }else if( pExpr->op==TK_FUNCTION ){ int d1; - char d2[3]; + char d2[4]; if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){ pWalker->eCode = 1; } @@ -127757,10 +129087,10 @@ static void codeCursorHint( ** ** Normally, this is just: ** -** OP_Seek $iCur $iRowid +** OP_DeferredSeek $iCur $iRowid ** ** However, if the scan currently being coded is a branch of an OR-loop and -** the statement currently being coded is a SELECT, then P3 of the OP_Seek +** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek ** is set to iIdxCur and P4 is set to point to an array of integers ** containing one entry for each column of the table cursor iCur is open ** on. For each table column, if the column is the i'th column of the @@ -127779,7 +129109,7 @@ static void codeDeferredSeek( assert( iIdxCur>0 ); assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 ); - sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur); + sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) ){ @@ -127808,7 +129138,7 @@ static void codeDeferredSeek( */ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){ assert( nReg>0 ); - if( sqlite3ExprIsVector(p) ){ + if( p && sqlite3ExprIsVector(p) ){ #ifndef SQLITE_OMIT_SUBQUERY if( (p->flags & EP_xIsSelect) ){ Vdbe *v = pParse->pVdbe; @@ -127849,7 +129179,7 @@ typedef struct IdxExprTrans { */ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ IdxExprTrans *pX = p->u.pIdxTrans; - if( sqlite3ExprCompare(pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; @@ -127861,9 +129191,9 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ } /* -** For an indexes on expression X, locate every instance of expression X in pExpr -** and change that subexpression into a reference to the appropriate column of -** the index. +** For an indexes on expression X, locate every instance of expression X +** in pExpr and change that subexpression into a reference to the appropriate +** column of the index. */ static void whereIndexExprTrans( Index *pIdx, /* The Index */ @@ -127921,7 +129251,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ Index *pIdx = 0; /* Index used by loop (if any) */ - int loopAgain; /* True if constraint generator loop should repeat */ + int iLoop; /* Iteration of constraint generator loop */ pParse = pWInfo->pParse; v = pParse->pVdbe; @@ -128816,13 +130146,20 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. ** - ** This loop may run either once (pIdx==0) or twice (pIdx!=0). If - ** it is run twice, then the first iteration codes those sub-expressions - ** that can be computed using columns from pIdx only (without seeking - ** the main table cursor). + ** This loop may run between one and three times, depending on the + ** constraints to be generated. The value of stack variable iLoop + ** determines the constraints coded by each iteration, as follows: + ** + ** iLoop==1: Code only expressions that are entirely covered by pIdx. + ** iLoop==2: Code remaining expressions that do not contain correlated + ** sub-queries. + ** iLoop==3: Code all remaining expressions. + ** + ** An effort is made to skip unnecessary iterations of the loop. */ + iLoop = (pIdx ? 1 : 2); do{ - loopAgain = 0; + int iNext = 0; /* Next value for iLoop */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; int skipLikeAddr = 0; @@ -128840,10 +130177,16 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } - if( pIdx && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ - loopAgain = 1; + + if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ + iNext = 2; continue; } + if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){ + if( iNext==0 ) iNext = 3; + continue; + } + if( pTerm->wtFlags & TERM_LIKECOND ){ /* If the TERM_LIKECOND flag is set, that means that the range search ** is sufficient to guarantee that the LIKE operator is true, so we @@ -128859,12 +130202,18 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverage(v); #endif } +#ifdef WHERETRACE_ENABLED /* 0xffff */ + if( sqlite3WhereTrace ){ + VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d", + pWC->nTerm-j, pTerm, iLoop)); + } +#endif sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); pTerm->wtFlags |= TERM_CODED; } - pIdx = 0; - }while( loopAgain ); + iLoop = iNext; + }while( iLoop>0 ); /* Insert code to test for implied constraints based on transitivity ** of the "==" operator. @@ -129121,12 +130470,12 @@ static int isLikeOrGlob( int *pisComplete, /* True if the only wildcard is % in the last character */ int *pnoCase /* True if uppercase is equivalent to lowercase */ ){ - const char *z = 0; /* String on RHS of LIKE operator */ + const u8 *z = 0; /* String on RHS of LIKE operator */ Expr *pRight, *pLeft; /* Right and left size of LIKE operator */ ExprList *pList; /* List of operands to the LIKE operator */ int c; /* One character in z[] */ int cnt; /* Number of non-wildcard prefix characters */ - char wc[3]; /* Wildcard characters */ + char wc[4]; /* Wildcard characters */ sqlite3 *db = pParse->db; /* Database connection */ sqlite3_value *pVal = 0; int op; /* Opcode of pRight */ @@ -129143,17 +130492,17 @@ static int isLikeOrGlob( pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); op = pRight->op; - if( op==TK_VARIABLE ){ + if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ Vdbe *pReprepare = pParse->pReprepare; int iCol = pRight->iColumn; pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB); if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){ - z = (char *)sqlite3_value_text(pVal); + z = sqlite3_value_text(pVal); } sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); }else if( op==TK_STRING ){ - z = pRight->u.zToken; + z = (u8*)pRight->u.zToken; } if( z ){ @@ -129173,16 +130522,42 @@ static int isLikeOrGlob( return 0; } } + + /* Count the number of prefix characters prior to the first wildcard */ cnt = 0; while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; + if( c==wc[3] && z[cnt]!=0 ) cnt++; } + + /* The optimization is possible only if (1) the pattern does not begin + ** with a wildcard and if (2) the non-wildcard prefix does not end with + ** an (illegal 0xff) character. The second condition is necessary so + ** that we can increment the prefix key to find an upper bound for the + ** range search. + */ if( cnt!=0 && 255!=(u8)z[cnt-1] ){ Expr *pPrefix; + + /* A "complete" match if the pattern ends with "*" or "%" */ *pisComplete = c==wc[0] && z[cnt+1]==0; - pPrefix = sqlite3Expr(db, TK_STRING, z); - if( pPrefix ) pPrefix->u.zToken[cnt] = 0; + + /* Get the pattern prefix. Remove all escapes from the prefix. */ + pPrefix = sqlite3Expr(db, TK_STRING, (char*)z); + if( pPrefix ){ + int iFrom, iTo; + char *zNew = pPrefix->u.zToken; + zNew[cnt] = 0; + for(iFrom=iTo=0; iFrom<cnt; iFrom++){ + if( zNew[iFrom]==wc[3] ) iFrom++; + zNew[iTo++] = zNew[iFrom]; + } + zNew[iTo] = 0; + } *ppPrefix = pPrefix; + + /* If the RHS pattern is a bound parameter, make arrangements to + ** reprepare the statement when that parameter is rebound */ if( op==TK_VARIABLE ){ Vdbe *v = pParse->pVdbe; sqlite3VdbeSetVarmask(v, pRight->iColumn); @@ -129213,48 +130588,84 @@ static int isLikeOrGlob( #ifndef SQLITE_OMIT_VIRTUALTABLE /* -** Check to see if the given expression is of the form -** -** column OP expr -** -** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a -** column of a virtual table. -** -** If it is then return TRUE. If not, return FALSE. -*/ -static int isMatchOfColumn( +** Check to see if the pExpr expression is a form that needs to be passed +** to the xBestIndex method of virtual tables. Forms of interest include: +** +** Expression Virtual Table Operator +** ----------------------- --------------------------------- +** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH +** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB +** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE +** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP +** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE +** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE +** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT +** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT +** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL +** +** In every case, "column" must be a column of a virtual table. If there +** is a match, set *ppLeft to the "column" expression, set *ppRight to the +** "expr" expression (even though in forms (6) and (8) the column is on the +** right and the expression is on the left). Also set *peOp2 to the +** appropriate virtual table operator. The return value is 1 or 2 if there +** is a match. The usual return is 1, but if the RHS is also a column +** of virtual table in forms (5) or (7) then return 2. +** +** If the expression matches none of the patterns above, return 0. +*/ +static int isAuxiliaryVtabOperator( Expr *pExpr, /* Test this expression */ - unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */ -){ - static const struct Op2 { - const char *zOp; - unsigned char eOp2; - } aOp[] = { - { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, - { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, - { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, - { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } - }; - ExprList *pList; - Expr *pCol; /* Column reference */ - int i; + unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ + Expr **ppLeft, /* Column expression to left of MATCH/op2 */ + Expr **ppRight /* Expression to left of MATCH/op2 */ +){ + if( pExpr->op==TK_FUNCTION ){ + static const struct Op2 { + const char *zOp; + unsigned char eOp2; + } aOp[] = { + { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, + { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, + { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, + { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } + }; + ExprList *pList; + Expr *pCol; /* Column reference */ + int i; - if( pExpr->op!=TK_FUNCTION ){ - return 0; - } - pList = pExpr->x.pList; - if( pList==0 || pList->nExpr!=2 ){ - return 0; - } - pCol = pList->a[1].pExpr; - if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ - return 0; - } - for(i=0; i<ArraySize(aOp); i++){ - if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ - *peOp2 = aOp[i].eOp2; - return 1; + pList = pExpr->x.pList; + if( pList==0 || pList->nExpr!=2 ){ + return 0; + } + pCol = pList->a[1].pExpr; + if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ + return 0; + } + for(i=0; i<ArraySize(aOp); i++){ + if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; + *ppRight = pList->a[0].pExpr; + *ppLeft = pCol; + return 1; + } + } + }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ + int res = 0; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; + if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ + res++; } + if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){ + res++; + SWAP(Expr*, pLeft, pRight); + } + *ppLeft = pLeft; + *ppRight = pRight; + if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE; + if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT; + if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL; + return res; } return 0; } @@ -129333,8 +130744,8 @@ static void whereCombineDisjuncts( && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); - if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; - if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return; + if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; + if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return; /* If we reach this point, it means the two subterms can be combined */ if( (eOp & (eOp-1))!=0 ){ if( eOp & (WO_LT|WO_LE) ){ @@ -129505,7 +130916,7 @@ static void exprAnalyzeOrTerm( for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ assert( pAndTerm->pExpr ); if( allowedOp(pAndTerm->pExpr->op) - || pAndTerm->eOperator==WO_MATCH + || pAndTerm->eOperator==WO_AUX ){ b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); } @@ -129707,7 +131118,6 @@ static void exprAnalyzeOrTerm( static int termIsEquivalence(Parse *pParse, Expr *pExpr){ char aff1, aff2; CollSeq *pColl; - const char *zColl1, *zColl2; if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; @@ -129720,11 +131130,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){ } pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight); if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1; - pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft); - zColl1 = pColl ? pColl->zName : 0; - pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight); - zColl2 = pColl ? pColl->zName : 0; - return sqlite3_stricmp(zColl1, zColl2)==0; + return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight); } /* @@ -129878,7 +131284,9 @@ static void exprAnalyze( }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); } + pMaskSet->bVarSelect = 0; prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr); + if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; if( ExprHasProperty(pExpr, EP_FromJoin) ){ Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); prereqAll |= x; @@ -130085,38 +131493,46 @@ static void exprAnalyze( #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ #ifndef SQLITE_OMIT_VIRTUALTABLE - /* Add a WO_MATCH auxiliary term to the constraint set if the - ** current expression is of the form: column MATCH expr. + /* Add a WO_AUX auxiliary term to the constraint set if the + ** current expression is of the form "column OP expr" where OP + ** is an operator that gets passed into virtual tables but which is + ** not normally optimized for ordinary tables. In other words, OP + ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL. ** This information is used by the xBestIndex methods of ** virtual tables. The native query optimizer does not attempt ** to do anything with MATCH functions. */ - if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){ - int idxNew; + if( pWC->op==TK_AND ){ Expr *pRight, *pLeft; - WhereTerm *pNewTerm; - Bitmask prereqColumn, prereqExpr; - - pRight = pExpr->x.pList->a[0].pExpr; - pLeft = pExpr->x.pList->a[1].pExpr; - prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); - prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); - if( (prereqExpr & prereqColumn)==0 ){ - Expr *pNewExpr; - pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, sqlite3ExprDup(db, pRight, 0)); - idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); - testcase( idxNew==0 ); - pNewTerm = &pWC->a[idxNew]; - pNewTerm->prereqRight = prereqExpr; - pNewTerm->leftCursor = pLeft->iTable; - pNewTerm->u.leftColumn = pLeft->iColumn; - pNewTerm->eOperator = WO_MATCH; - pNewTerm->eMatchOp = eOp2; - markTermAsChild(pWC, idxNew, idxTerm); - pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags |= TERM_COPIED; - pNewTerm->prereqAll = pTerm->prereqAll; + int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight); + while( res-- > 0 ){ + int idxNew; + WhereTerm *pNewTerm; + Bitmask prereqColumn, prereqExpr; + + prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); + prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); + if( (prereqExpr & prereqColumn)==0 ){ + Expr *pNewExpr; + pNewExpr = sqlite3PExpr(pParse, TK_MATCH, + 0, sqlite3ExprDup(db, pRight, 0)); + if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ + ExprSetProperty(pNewExpr, EP_FromJoin); + } + idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); + testcase( idxNew==0 ); + pNewTerm = &pWC->a[idxNew]; + pNewTerm->prereqRight = prereqExpr; + pNewTerm->leftCursor = pLeft->iTable; + pNewTerm->u.leftColumn = pLeft->iColumn; + pNewTerm->eOperator = WO_AUX; + pNewTerm->eMatchOp = eOp2; + markTermAsChild(pWC, idxNew, idxTerm); + pTerm = &pWC->a[idxTerm]; + pTerm->wtFlags |= TERM_COPIED; + pNewTerm->prereqAll = pTerm->prereqAll; + } + SWAP(Expr*, pLeft, pRight); } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -130306,9 +131722,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ } mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; assert( !ExprHasProperty(p, EP_TokenOnly) ); - if( p->pRight ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight); if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft); - if( ExprHasProperty(p, EP_xIsSelect) ){ + if( p->pRight ){ + mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight); + assert( p->x.pList==0 ); + }else if( ExprHasProperty(p, EP_xIsSelect) ){ + if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1; mask |= exprSelectUsage(pMaskSet, p->x.pSelect); }else if( p->x.pList ){ mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); @@ -130792,8 +132211,8 @@ static int findIndexCol( && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase ){ - CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); - if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){ + CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr); + if( 0==sqlite3StrICmp(pColl->zName, zColl) ){ return i; } } @@ -130997,6 +132416,15 @@ static int termCanDriveIndex( char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0; + if( (pSrc->fg.jointype & JT_LEFT) + && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + && (pTerm->eOperator & WO_IS) + ){ + /* Cannot use an IS term from the WHERE clause as an index driver for + ** the RHS of a LEFT JOIN. Such a term can only be used if it is from + ** the ON clause. */ + return 0; + } if( (pTerm->prereqRight & notReady)!=0 ) return 0; if( pTerm->u.leftColumn<0 ) return 0; aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; @@ -131248,7 +132676,7 @@ static sqlite3_index_info *allocateIndexInfo( testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_IS ); testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; + if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; assert( pTerm->u.leftColumn>=(-1) ); nTerm++; @@ -131296,7 +132724,7 @@ static sqlite3_index_info *allocateIndexInfo( pUsage; for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ - u8 op; + u16 op; if( pTerm->leftCursor != pSrc->iCursor ) continue; if( pTerm->prereqRight & mUnusable ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); @@ -131304,34 +132732,40 @@ static sqlite3_index_info *allocateIndexInfo( testcase( pTerm->eOperator & WO_IS ); testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue; + if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; assert( pTerm->u.leftColumn>=(-1) ); pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; - op = (u8)pTerm->eOperator & WO_ALL; + op = pTerm->eOperator & WO_ALL; if( op==WO_IN ) op = WO_EQ; - if( op==WO_MATCH ){ - op = pTerm->eMatchOp; - } - pIdxCons[j].op = op; - /* The direct assignment in the previous line is possible only because - ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The - ** following asserts verify this fact. */ - assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); - assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); - assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); - assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); - assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); - assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH ); - assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); - - if( op & (WO_LT|WO_LE|WO_GT|WO_GE) - && sqlite3ExprIsVector(pTerm->pExpr->pRight) - ){ - if( i<16 ) mNoOmit |= (1 << i); - if( op==WO_LT ) pIdxCons[j].op = WO_LE; - if( op==WO_GT ) pIdxCons[j].op = WO_GE; + if( op==WO_AUX ){ + pIdxCons[j].op = pTerm->eMatchOp; + }else if( op & (WO_ISNULL|WO_IS) ){ + if( op==WO_ISNULL ){ + pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL; + }else{ + pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS; + } + }else{ + pIdxCons[j].op = (u8)op; + /* The direct assignment in the previous line is possible only because + ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The + ** following asserts verify this fact. */ + assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ ); + assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT ); + assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE ); + assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT ); + assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE ); + assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) ); + + if( op & (WO_LT|WO_LE|WO_GT|WO_GE) + && sqlite3ExprIsVector(pTerm->pExpr->pRight) + ){ + if( i<16 ) mNoOmit |= (1 << i); + if( op==WO_LT ) pIdxCons[j].op = WO_LE; + if( op==WO_GT ) pIdxCons[j].op = WO_GE; + } } j++; @@ -131581,7 +133015,7 @@ static int whereKeyStats( iGap = iGap/3; } aStat[0] = iLower + iGap; - aStat[1] = pIdx->aAvgEq[iCol]; + aStat[1] = pIdx->aAvgEq[nField-1]; } /* Restore the pRec->nField value before returning. */ @@ -132259,18 +133693,19 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ ** Return TRUE if all of the following are true: ** ** (1) X has the same or lower cost that Y -** (2) X is a proper subset of Y -** (3) X skips at least as many columns as Y -** -** By "proper subset" we mean that X uses fewer WHERE clause terms -** than Y and that every WHERE clause term used by X is also used -** by Y. +** (2) X uses fewer WHERE clause terms than Y +** (3) Every WHERE clause term used by X is also used by Y +** (4) X skips at least as many columns as Y +** (5) If X is a covering index, than Y is too ** +** Conditions (2) and (3) mean that X is a "proper subset" of Y. ** If X is a proper subset of Y then Y is a better choice and ought ** to have a lower cost. This routine returns TRUE when that cost -** relationship is inverted and needs to be adjusted. The third rule +** relationship is inverted and needs to be adjusted. Constraint (4) ** was added because if X uses skip-scan less than Y it still might -** deserve a lower cost even if it is a proper subset of Y. +** deserve a lower cost even if it is a proper subset of Y. Constraint (5) +** was added because a covering index probably deserves to have a lower cost +** than a non-covering index even if it is a proper subset. */ static int whereLoopCheaperProperSubset( const WhereLoop *pX, /* First WhereLoop to compare */ @@ -132292,6 +133727,10 @@ static int whereLoopCheaperProperSubset( } if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */ } + if( (pX->wsFlags&WHERE_IDX_ONLY)!=0 + && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){ + return 0; /* Constraint (5) */ + } return 1; /* All conditions meet */ } @@ -132334,16 +133773,17 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){ /* ** Search the list of WhereLoops in *ppPrev looking for one that can be -** supplanted by pTemplate. +** replaced by pTemplate. ** -** Return NULL if the WhereLoop list contains an entry that can supplant -** pTemplate, in other words if pTemplate does not belong on the list. +** Return NULL if pTemplate does not belong on the WhereLoop list. +** In other words if pTemplate ought to be dropped from further consideration. ** -** If pX is a WhereLoop that pTemplate can supplant, then return the +** If pX is a WhereLoop that pTemplate can replace, then return the ** link that points to pX. ** -** If pTemplate cannot supplant any existing element of the list but needs -** to be added to the list, then return a pointer to the tail of the list. +** If pTemplate cannot replace any existing element of the list but needs +** to be added to the list as a new entry, then return a pointer to the +** tail of the list. */ static WhereLoop **whereLoopFindLesser( WhereLoop **ppPrev, @@ -132488,8 +133928,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ if( p!=0 ){ sqlite3DebugPrintf("replace: "); whereLoopPrint(p, pBuilder->pWC); + sqlite3DebugPrintf(" with: "); + }else{ + sqlite3DebugPrintf(" add: "); } - sqlite3DebugPrintf(" add: "); whereLoopPrint(pTemplate, pBuilder->pWC); } #endif @@ -133040,7 +134482,7 @@ static int indexMightHelpWithOrderBy( }else if( (aColExpr = pIndex->aColExpr)!=0 ){ for(jj=0; jj<pIndex->nKeyCol; jj++){ if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; - if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ + if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ return 1; } } @@ -133073,14 +134515,16 @@ static Bitmask columnsInIndex(Index *pIdx){ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ int i; WhereTerm *pTerm; + Parse *pParse = pWC->pWInfo->pParse; while( pWhere->op==TK_AND ){ if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0; pWhere = pWhere->pRight; } + if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0; for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ Expr *pExpr = pTerm->pExpr; - if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab) - && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) + if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) + && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) ){ return 1; } @@ -133948,14 +135392,10 @@ static i8 wherePathSatisfiesOrderBy( if( j>=pLoop->nLTerm ) continue; } if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){ - const char *z1, *z2; - pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); - if( !pColl ) pColl = db->pDfltColl; - z1 = pColl->zName; - pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr); - if( !pColl ) pColl = db->pDfltColl; - z2 = pColl->zName; - if( sqlite3StrICmp(z1, z2)!=0 ) continue; + if( sqlite3ExprCollSeqMatch(pWInfo->pParse, + pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){ + continue; + } testcase( pTerm->pExpr->op==TK_IS ); } obSat |= MASKBIT(i); @@ -134027,7 +135467,7 @@ static i8 wherePathSatisfiesOrderBy( if( pIndex ){ iColumn = pIndex->aiColumn[j]; revIdx = pIndex->aSortOrder[j]; - if( iColumn==pIndex->pTable->iPKey ) iColumn = -1; + if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; }else{ iColumn = XN_ROWID; revIdx = 0; @@ -134054,18 +135494,18 @@ static i8 wherePathSatisfiesOrderBy( testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; - if( iColumn>=(-1) ){ + if( iColumn>=XN_ROWID ){ if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; if( pOBExpr->iColumn!=iColumn ) continue; }else{ - if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ + Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr; + if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){ continue; } } - if( iColumn>=0 ){ - pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); - if( !pColl ) pColl = db->pDfltColl; + if( iColumn!=XN_ROWID ){ + pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue; } pLoop->u.btree.nIdxCol = j+1; @@ -134358,6 +135798,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ rUnsorted, rCost)); }else{ rCost = rUnsorted; + rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */ } /* Check to see if pWLoop should be added to the set of @@ -134389,8 +135830,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ ** this candidate as not viable. */ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, + sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); } #endif @@ -134408,26 +135849,36 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pTo = &aTo[jj]; #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ - sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, + sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); } #endif }else{ /* Control reaches here if best-so-far path pTo=aTo[jj] covers the - ** same set of loops and has the sam isOrdered setting as the + ** same set of loops and has the same isOrdered setting as the ** candidate path. Check to see if the candidate should replace - ** pTo or if the candidate should be skipped */ - if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){ + ** pTo or if the candidate should be skipped. + ** + ** The conditional is an expanded vector comparison equivalent to: + ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted) + */ + if( pTo->rCost<rCost + || (pTo->rCost==rCost + && (pTo->nRow<nOut + || (pTo->nRow==nOut && pTo->rUnsorted<=rUnsorted) + ) + ) + ){ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( - "Skip %s cost=%-3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, + "Skip %s cost=%-3d,%3d,%3d order=%c", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); - sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n", + sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); + pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); } #endif /* Discard the candidate path from further consideration */ @@ -134440,12 +135891,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ #ifdef WHERETRACE_ENABLED /* 0x4 */ if( sqlite3WhereTrace&0x4 ){ sqlite3DebugPrintf( - "Update %s cost=%-3d,%3d order=%c", - wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, + "Update %s cost=%-3d,%3d,%3d order=%c", + wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted, isOrdered>=0 ? isOrdered+'0' : '?'); - sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n", + sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, - pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); + pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?'); } #endif } @@ -134671,6 +136122,32 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ } /* +** Helper function for exprIsDeterministic(). +*/ +static int exprNodeIsDeterministic(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_ConstFunc)==0 ){ + pWalker->eCode = 0; + return WRC_Abort; + } + return WRC_Continue; +} + +/* +** Return true if the expression contains no non-deterministic SQL +** functions. Do not consider non-deterministic SQL functions that are +** part of sub-select statements. +*/ +static int exprIsDeterministic(Expr *p){ + Walker w; + memset(&w, 0, sizeof(w)); + w.eCode = 1; + w.xExprCallback = exprNodeIsDeterministic; + w.xSelectCallback = sqlite3SelectWalkFail; + sqlite3WalkExpr(&w, p); + return w.eCode; +} + +/* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains ** information needed to terminate the loop. Later, the calling routine @@ -134868,17 +136345,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); - /* Special case: a WHERE clause that is constant. Evaluate the - ** expression and either jump over all of the code or fall thru. - */ - for(ii=0; ii<sWLB.pWC->nTerm; ii++){ - if( nTabList==0 || sqlite3ExprIsConstantNotJoin(sWLB.pWC->a[ii].pExpr) ){ - sqlite3ExprIfFalse(pParse, sWLB.pWC->a[ii].pExpr, pWInfo->iBreak, - SQLITE_JUMPIFNULL); - sWLB.pWC->a[ii].wtFlags |= TERM_CODED; - } - } - /* Special case: No FROM clause */ if( nTabList==0 ){ @@ -134886,36 +136352,60 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } + }else{ + /* Assign a bit from the bitmask to every term in the FROM clause. + ** + ** The N-th term of the FROM clause is assigned a bitmask of 1<<N. + ** + ** The rule of the previous sentence ensures thta if X is the bitmask for + ** a table T, then X-1 is the bitmask for all other tables to the left of T. + ** Knowing the bitmask for all tables to the left of a left join is + ** important. Ticket #3015. + ** + ** Note that bitmasks are created for all pTabList->nSrc tables in + ** pTabList, not just the first nTabList tables. nTabList is normally + ** equal to pTabList->nSrc but might be shortened to 1 if the + ** WHERE_OR_SUBCLAUSE flag is set. + */ + ii = 0; + do{ + createMask(pMaskSet, pTabList->a[ii].iCursor); + sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); + }while( (++ii)<pTabList->nSrc ); + #ifdef SQLITE_DEBUG + { + Bitmask mx = 0; + for(ii=0; ii<pTabList->nSrc; ii++){ + Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); + assert( m>=mx ); + mx = m; + } + } + #endif } + + /* Analyze all of the subexpressions. */ + sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); + if( db->mallocFailed ) goto whereBeginError; - /* Assign a bit from the bitmask to every term in the FROM clause. + /* Special case: WHERE terms that do not refer to any tables in the join + ** (constant expressions). Evaluate each such term, and jump over all the + ** generated code if the result is not true. ** - ** The N-th term of the FROM clause is assigned a bitmask of 1<<N. + ** Do not do this if the expression contains non-deterministic functions + ** that are not within a sub-select. This is not strictly required, but + ** preserves SQLite's legacy behaviour in the following two cases: ** - ** The rule of the previous sentence ensures thta if X is the bitmask for - ** a table T, then X-1 is the bitmask for all other tables to the left of T. - ** Knowing the bitmask for all tables to the left of a left join is - ** important. Ticket #3015. - ** - ** Note that bitmasks are created for all pTabList->nSrc tables in - ** pTabList, not just the first nTabList tables. nTabList is normally - ** equal to pTabList->nSrc but might be shortened to 1 if the - ** WHERE_OR_SUBCLAUSE flag is set. + ** FROM ... WHERE random()>0; -- eval random() once per row + ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall */ - for(ii=0; ii<pTabList->nSrc; ii++){ - createMask(pMaskSet, pTabList->a[ii].iCursor); - sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); - } -#ifdef SQLITE_DEBUG - for(ii=0; ii<pTabList->nSrc; ii++){ - Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor); - assert( m==MASKBIT(ii) ); + for(ii=0; ii<sWLB.pWC->nTerm; ii++){ + WhereTerm *pT = &sWLB.pWC->a[ii]; + if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ + sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); + pT->wtFlags |= TERM_CODED; + } } -#endif - - /* Analyze all of the subexpressions. */ - sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); - if( db->mallocFailed ) goto whereBeginError; if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ @@ -134953,7 +136443,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ - p->cId = zLabel[i%sizeof(zLabel)]; + p->cId = zLabel[i%(sizeof(zLabel)-1)]; whereLoopPrint(p, sWLB.pWC); } } @@ -135116,7 +136606,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( Index *pIx = pLoop->u.btree.pIndex; int iIndexCur; int op = OP_OpenRead; - /* iAuxArg is always set if to a positive value if ONEPASS is possible */ + /* iAuxArg is always set to a positive value if ONEPASS is possible */ assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 ); if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx) && (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0 @@ -135697,7 +137187,8 @@ static void disableLookaside(Parse *pParse){ ** YY_MAX_SHIFT Maximum value for shift actions ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_MIN_REDUCE Maximum value for reduce actions +** YY_MIN_REDUCE Minimum value for reduce actions +** YY_MAX_REDUCE Maximum value for reduce actions ** YY_ERROR_ACTION The yy_action[] code for syntax error ** YY_ACCEPT_ACTION The yy_action[] code for accept ** YY_NO_ACTION The yy_action[] code for no-op @@ -135709,7 +137200,7 @@ static void disableLookaside(Parse *pParse){ #define YYCODETYPE unsigned char #define YYNOCODE 252 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 69 +#define YYWILDCARD 83 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; @@ -135735,16 +137226,16 @@ typedef union { #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYFALLBACK 1 -#define YYNSTATE 456 -#define YYNRULE 332 -#define YY_MAX_SHIFT 455 -#define YY_MIN_SHIFTREDUCE 668 -#define YY_MAX_SHIFTREDUCE 999 -#define YY_MIN_REDUCE 1000 -#define YY_MAX_REDUCE 1331 -#define YY_ERROR_ACTION 1332 -#define YY_ACCEPT_ACTION 1333 -#define YY_NO_ACTION 1334 +#define YYNSTATE 455 +#define YYNRULE 329 +#define YY_MAX_SHIFT 454 +#define YY_MIN_SHIFTREDUCE 664 +#define YY_MAX_SHIFTREDUCE 992 +#define YY_MIN_REDUCE 993 +#define YY_MAX_REDUCE 1321 +#define YY_ERROR_ACTION 1322 +#define YY_ACCEPT_ACTION 1323 +#define YY_NO_ACTION 1324 /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined @@ -135818,461 +137309,461 @@ typedef union { *********** Begin parsing tables **********************************************/ #define YY_ACTTAB_COUNT (1566) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 325, 411, 343, 752, 752, 203, 946, 354, 976, 98, - /* 10 */ 98, 98, 98, 91, 96, 96, 96, 96, 95, 95, - /* 20 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 813, - /* 30 */ 978, 978, 98, 98, 98, 98, 20, 96, 96, 96, - /* 40 */ 96, 95, 95, 94, 94, 94, 93, 351, 92, 89, - /* 50 */ 178, 99, 100, 90, 853, 856, 845, 845, 97, 97, - /* 60 */ 98, 98, 98, 98, 351, 96, 96, 96, 96, 95, - /* 70 */ 95, 94, 94, 94, 93, 351, 325, 340, 976, 262, - /* 80 */ 365, 251, 212, 169, 287, 405, 282, 404, 199, 791, - /* 90 */ 242, 412, 21, 957, 379, 280, 93, 351, 792, 95, - /* 100 */ 95, 94, 94, 94, 93, 351, 978, 978, 96, 96, - /* 110 */ 96, 96, 95, 95, 94, 94, 94, 93, 351, 813, - /* 120 */ 329, 242, 412, 913, 832, 913, 132, 99, 100, 90, - /* 130 */ 853, 856, 845, 845, 97, 97, 98, 98, 98, 98, - /* 140 */ 450, 96, 96, 96, 96, 95, 95, 94, 94, 94, - /* 150 */ 93, 351, 325, 825, 349, 348, 120, 819, 120, 75, - /* 160 */ 52, 52, 957, 958, 959, 760, 984, 146, 361, 262, - /* 170 */ 370, 261, 957, 982, 961, 983, 92, 89, 178, 371, - /* 180 */ 230, 371, 978, 978, 817, 361, 360, 101, 824, 824, - /* 190 */ 826, 384, 24, 964, 381, 428, 413, 369, 985, 380, - /* 200 */ 985, 708, 325, 99, 100, 90, 853, 856, 845, 845, - /* 210 */ 97, 97, 98, 98, 98, 98, 373, 96, 96, 96, - /* 220 */ 96, 95, 95, 94, 94, 94, 93, 351, 957, 132, - /* 230 */ 897, 450, 978, 978, 896, 60, 94, 94, 94, 93, - /* 240 */ 351, 957, 958, 959, 961, 103, 361, 957, 385, 334, - /* 250 */ 702, 52, 52, 99, 100, 90, 853, 856, 845, 845, - /* 260 */ 97, 97, 98, 98, 98, 98, 698, 96, 96, 96, - /* 270 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 455, - /* 280 */ 670, 450, 227, 61, 157, 243, 344, 114, 701, 888, - /* 290 */ 147, 832, 957, 373, 747, 957, 320, 957, 958, 959, - /* 300 */ 194, 10, 10, 402, 399, 398, 888, 890, 978, 978, - /* 310 */ 762, 171, 170, 157, 397, 337, 957, 958, 959, 702, - /* 320 */ 825, 310, 153, 957, 819, 321, 82, 23, 80, 99, - /* 330 */ 100, 90, 853, 856, 845, 845, 97, 97, 98, 98, - /* 340 */ 98, 98, 894, 96, 96, 96, 96, 95, 95, 94, - /* 350 */ 94, 94, 93, 351, 325, 824, 824, 826, 277, 231, - /* 360 */ 300, 957, 958, 959, 957, 958, 959, 888, 194, 25, - /* 370 */ 450, 402, 399, 398, 957, 355, 300, 450, 957, 74, - /* 380 */ 450, 1, 397, 132, 978, 978, 957, 224, 224, 813, - /* 390 */ 10, 10, 957, 958, 959, 968, 132, 52, 52, 415, - /* 400 */ 52, 52, 739, 739, 339, 99, 100, 90, 853, 856, - /* 410 */ 845, 845, 97, 97, 98, 98, 98, 98, 790, 96, - /* 420 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, - /* 430 */ 325, 789, 428, 418, 706, 428, 427, 1270, 1270, 262, - /* 440 */ 370, 261, 957, 957, 958, 959, 757, 957, 958, 959, - /* 450 */ 450, 756, 450, 734, 713, 957, 958, 959, 443, 711, - /* 460 */ 978, 978, 734, 394, 92, 89, 178, 447, 447, 447, - /* 470 */ 51, 51, 52, 52, 439, 778, 700, 92, 89, 178, - /* 480 */ 172, 99, 100, 90, 853, 856, 845, 845, 97, 97, - /* 490 */ 98, 98, 98, 98, 198, 96, 96, 96, 96, 95, - /* 500 */ 95, 94, 94, 94, 93, 351, 325, 428, 408, 916, - /* 510 */ 699, 957, 958, 959, 92, 89, 178, 224, 224, 157, - /* 520 */ 241, 221, 419, 299, 776, 917, 416, 375, 450, 415, - /* 530 */ 58, 324, 737, 737, 920, 379, 978, 978, 379, 777, - /* 540 */ 449, 918, 363, 740, 296, 686, 9, 9, 52, 52, - /* 550 */ 234, 330, 234, 256, 417, 741, 280, 99, 100, 90, - /* 560 */ 853, 856, 845, 845, 97, 97, 98, 98, 98, 98, - /* 570 */ 450, 96, 96, 96, 96, 95, 95, 94, 94, 94, - /* 580 */ 93, 351, 325, 423, 72, 450, 833, 120, 368, 450, - /* 590 */ 10, 10, 5, 301, 203, 450, 177, 976, 253, 420, - /* 600 */ 255, 776, 200, 175, 233, 10, 10, 842, 842, 36, - /* 610 */ 36, 1299, 978, 978, 729, 37, 37, 349, 348, 425, - /* 620 */ 203, 260, 776, 976, 232, 937, 1326, 876, 338, 1326, - /* 630 */ 422, 854, 857, 99, 100, 90, 853, 856, 845, 845, - /* 640 */ 97, 97, 98, 98, 98, 98, 268, 96, 96, 96, - /* 650 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 846, - /* 660 */ 450, 985, 818, 985, 1209, 450, 916, 976, 720, 350, - /* 670 */ 350, 350, 935, 177, 450, 937, 1327, 254, 198, 1327, - /* 680 */ 12, 12, 917, 403, 450, 27, 27, 250, 978, 978, - /* 690 */ 118, 721, 162, 976, 38, 38, 268, 176, 918, 776, - /* 700 */ 433, 1275, 946, 354, 39, 39, 317, 998, 325, 99, - /* 710 */ 100, 90, 853, 856, 845, 845, 97, 97, 98, 98, - /* 720 */ 98, 98, 935, 96, 96, 96, 96, 95, 95, 94, - /* 730 */ 94, 94, 93, 351, 450, 330, 450, 358, 978, 978, - /* 740 */ 717, 317, 936, 341, 900, 900, 387, 673, 674, 675, - /* 750 */ 275, 996, 318, 999, 40, 40, 41, 41, 268, 99, - /* 760 */ 100, 90, 853, 856, 845, 845, 97, 97, 98, 98, - /* 770 */ 98, 98, 450, 96, 96, 96, 96, 95, 95, 94, - /* 780 */ 94, 94, 93, 351, 325, 450, 356, 450, 999, 450, - /* 790 */ 692, 331, 42, 42, 791, 270, 450, 273, 450, 228, - /* 800 */ 450, 298, 450, 792, 450, 28, 28, 29, 29, 31, - /* 810 */ 31, 450, 817, 450, 978, 978, 43, 43, 44, 44, - /* 820 */ 45, 45, 11, 11, 46, 46, 893, 78, 893, 268, - /* 830 */ 268, 105, 105, 47, 47, 99, 100, 90, 853, 856, - /* 840 */ 845, 845, 97, 97, 98, 98, 98, 98, 450, 96, - /* 850 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, - /* 860 */ 325, 450, 117, 450, 749, 158, 450, 696, 48, 48, - /* 870 */ 229, 919, 450, 928, 450, 415, 450, 335, 450, 245, - /* 880 */ 450, 33, 33, 49, 49, 450, 50, 50, 246, 817, - /* 890 */ 978, 978, 34, 34, 122, 122, 123, 123, 124, 124, - /* 900 */ 56, 56, 268, 81, 249, 35, 35, 197, 196, 195, - /* 910 */ 325, 99, 100, 90, 853, 856, 845, 845, 97, 97, - /* 920 */ 98, 98, 98, 98, 450, 96, 96, 96, 96, 95, - /* 930 */ 95, 94, 94, 94, 93, 351, 450, 696, 450, 817, - /* 940 */ 978, 978, 975, 884, 106, 106, 268, 886, 268, 944, - /* 950 */ 2, 892, 268, 892, 336, 716, 53, 53, 107, 107, - /* 960 */ 325, 99, 100, 90, 853, 856, 845, 845, 97, 97, - /* 970 */ 98, 98, 98, 98, 450, 96, 96, 96, 96, 95, - /* 980 */ 95, 94, 94, 94, 93, 351, 450, 746, 450, 742, - /* 990 */ 978, 978, 715, 267, 108, 108, 446, 331, 332, 133, - /* 1000 */ 223, 175, 301, 225, 386, 933, 104, 104, 121, 121, - /* 1010 */ 325, 99, 88, 90, 853, 856, 845, 845, 97, 97, - /* 1020 */ 98, 98, 98, 98, 817, 96, 96, 96, 96, 95, - /* 1030 */ 95, 94, 94, 94, 93, 351, 450, 347, 450, 167, - /* 1040 */ 978, 978, 932, 815, 372, 319, 202, 202, 374, 263, - /* 1050 */ 395, 202, 74, 208, 726, 727, 119, 119, 112, 112, - /* 1060 */ 325, 407, 100, 90, 853, 856, 845, 845, 97, 97, - /* 1070 */ 98, 98, 98, 98, 450, 96, 96, 96, 96, 95, - /* 1080 */ 95, 94, 94, 94, 93, 351, 450, 757, 450, 345, - /* 1090 */ 978, 978, 756, 278, 111, 111, 74, 719, 718, 709, - /* 1100 */ 286, 883, 754, 1289, 257, 77, 109, 109, 110, 110, - /* 1110 */ 908, 285, 810, 90, 853, 856, 845, 845, 97, 97, - /* 1120 */ 98, 98, 98, 98, 911, 96, 96, 96, 96, 95, - /* 1130 */ 95, 94, 94, 94, 93, 351, 86, 445, 450, 3, - /* 1140 */ 1202, 450, 745, 132, 352, 120, 689, 86, 445, 785, - /* 1150 */ 3, 767, 202, 377, 448, 352, 907, 120, 55, 55, - /* 1160 */ 450, 57, 57, 828, 879, 448, 450, 208, 450, 709, - /* 1170 */ 450, 883, 237, 434, 436, 120, 440, 429, 362, 120, - /* 1180 */ 54, 54, 132, 450, 434, 832, 52, 52, 26, 26, - /* 1190 */ 30, 30, 382, 132, 409, 444, 832, 694, 264, 390, - /* 1200 */ 116, 269, 272, 32, 32, 83, 84, 120, 274, 120, - /* 1210 */ 120, 276, 85, 352, 452, 451, 83, 84, 819, 730, - /* 1220 */ 714, 428, 430, 85, 352, 452, 451, 120, 120, 819, - /* 1230 */ 378, 218, 281, 828, 783, 816, 86, 445, 410, 3, - /* 1240 */ 763, 774, 431, 432, 352, 302, 303, 823, 697, 824, - /* 1250 */ 824, 826, 827, 19, 448, 691, 680, 679, 681, 951, - /* 1260 */ 824, 824, 826, 827, 19, 289, 159, 291, 293, 7, - /* 1270 */ 316, 173, 259, 434, 805, 364, 252, 910, 376, 713, - /* 1280 */ 295, 435, 168, 993, 400, 832, 284, 881, 880, 205, - /* 1290 */ 954, 308, 927, 86, 445, 990, 3, 925, 333, 144, - /* 1300 */ 130, 352, 72, 135, 59, 83, 84, 761, 137, 366, - /* 1310 */ 802, 448, 85, 352, 452, 451, 139, 226, 819, 140, - /* 1320 */ 156, 62, 315, 314, 313, 215, 311, 367, 393, 683, - /* 1330 */ 434, 185, 141, 912, 142, 160, 148, 812, 875, 383, - /* 1340 */ 189, 67, 832, 180, 389, 248, 895, 775, 219, 824, - /* 1350 */ 824, 826, 827, 19, 247, 190, 266, 154, 391, 271, - /* 1360 */ 191, 192, 83, 84, 682, 406, 733, 182, 322, 85, - /* 1370 */ 352, 452, 451, 732, 183, 819, 342, 132, 181, 711, - /* 1380 */ 731, 421, 76, 445, 705, 3, 323, 704, 283, 724, - /* 1390 */ 352, 771, 703, 966, 723, 71, 204, 6, 288, 290, - /* 1400 */ 448, 772, 770, 769, 79, 292, 824, 824, 826, 827, - /* 1410 */ 19, 294, 297, 438, 346, 442, 102, 861, 753, 434, - /* 1420 */ 238, 426, 73, 305, 239, 304, 326, 240, 424, 306, - /* 1430 */ 307, 832, 213, 688, 22, 952, 453, 214, 216, 217, - /* 1440 */ 454, 677, 115, 676, 671, 125, 126, 235, 127, 669, - /* 1450 */ 327, 83, 84, 359, 353, 244, 166, 328, 85, 352, - /* 1460 */ 452, 451, 134, 179, 819, 357, 113, 891, 811, 889, - /* 1470 */ 136, 128, 138, 743, 258, 184, 906, 143, 145, 63, - /* 1480 */ 64, 65, 66, 129, 909, 905, 187, 186, 8, 13, - /* 1490 */ 188, 265, 898, 149, 202, 824, 824, 826, 827, 19, - /* 1500 */ 388, 987, 150, 161, 285, 685, 392, 396, 151, 722, - /* 1510 */ 193, 68, 14, 401, 279, 15, 69, 236, 831, 830, - /* 1520 */ 131, 859, 751, 70, 16, 414, 755, 4, 784, 220, - /* 1530 */ 222, 174, 152, 437, 779, 201, 17, 77, 74, 18, - /* 1540 */ 874, 860, 858, 915, 863, 914, 207, 206, 941, 163, - /* 1550 */ 210, 942, 209, 164, 441, 862, 165, 211, 829, 695, - /* 1560 */ 87, 312, 309, 947, 1291, 1290, + /* 0 */ 324, 1323, 155, 155, 2, 203, 94, 94, 94, 93, + /* 10 */ 350, 98, 98, 98, 98, 91, 95, 95, 94, 94, + /* 20 */ 94, 93, 350, 268, 99, 100, 90, 971, 971, 847, + /* 30 */ 850, 839, 839, 97, 97, 98, 98, 98, 98, 350, + /* 40 */ 969, 96, 96, 96, 96, 95, 95, 94, 94, 94, + /* 50 */ 93, 350, 950, 96, 96, 96, 96, 95, 95, 94, + /* 60 */ 94, 94, 93, 350, 250, 96, 96, 96, 96, 95, + /* 70 */ 95, 94, 94, 94, 93, 350, 224, 224, 969, 132, + /* 80 */ 888, 348, 347, 415, 172, 324, 1286, 449, 414, 950, + /* 90 */ 951, 952, 808, 977, 1032, 950, 300, 786, 428, 132, + /* 100 */ 975, 362, 976, 9, 9, 787, 132, 52, 52, 99, + /* 110 */ 100, 90, 971, 971, 847, 850, 839, 839, 97, 97, + /* 120 */ 98, 98, 98, 98, 372, 978, 241, 978, 262, 369, + /* 130 */ 261, 120, 950, 951, 952, 194, 58, 324, 401, 398, + /* 140 */ 397, 808, 427, 429, 75, 808, 1260, 1260, 132, 396, + /* 150 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 160 */ 350, 99, 100, 90, 971, 971, 847, 850, 839, 839, + /* 170 */ 97, 97, 98, 98, 98, 98, 786, 262, 369, 261, + /* 180 */ 826, 262, 364, 251, 787, 1084, 101, 1114, 72, 324, + /* 190 */ 227, 1113, 242, 411, 442, 819, 92, 89, 178, 818, + /* 200 */ 1022, 268, 96, 96, 96, 96, 95, 95, 94, 94, + /* 210 */ 94, 93, 350, 99, 100, 90, 971, 971, 847, 850, + /* 220 */ 839, 839, 97, 97, 98, 98, 98, 98, 449, 372, + /* 230 */ 818, 818, 820, 92, 89, 178, 60, 92, 89, 178, + /* 240 */ 1025, 324, 357, 930, 1316, 300, 61, 1316, 52, 52, + /* 250 */ 836, 836, 848, 851, 96, 96, 96, 96, 95, 95, + /* 260 */ 94, 94, 94, 93, 350, 99, 100, 90, 971, 971, + /* 270 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, + /* 280 */ 92, 89, 178, 427, 412, 198, 930, 1317, 454, 995, + /* 290 */ 1317, 355, 1024, 324, 243, 231, 114, 277, 348, 347, + /* 300 */ 1242, 950, 416, 1071, 928, 840, 96, 96, 96, 96, + /* 310 */ 95, 95, 94, 94, 94, 93, 350, 99, 100, 90, + /* 320 */ 971, 971, 847, 850, 839, 839, 97, 97, 98, 98, + /* 330 */ 98, 98, 449, 328, 449, 120, 23, 256, 950, 951, + /* 340 */ 952, 968, 978, 438, 978, 324, 329, 928, 954, 701, + /* 350 */ 200, 175, 52, 52, 52, 52, 939, 353, 96, 96, + /* 360 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 99, + /* 370 */ 100, 90, 971, 971, 847, 850, 839, 839, 97, 97, + /* 380 */ 98, 98, 98, 98, 354, 449, 954, 427, 417, 427, + /* 390 */ 426, 1290, 92, 89, 178, 268, 253, 324, 255, 1058, + /* 400 */ 1037, 694, 93, 350, 383, 52, 52, 380, 1058, 374, + /* 410 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 420 */ 350, 99, 100, 90, 971, 971, 847, 850, 839, 839, + /* 430 */ 97, 97, 98, 98, 98, 98, 228, 449, 167, 449, + /* 440 */ 427, 407, 157, 446, 446, 446, 349, 349, 349, 324, + /* 450 */ 310, 316, 991, 827, 320, 242, 411, 51, 51, 36, + /* 460 */ 36, 254, 96, 96, 96, 96, 95, 95, 94, 94, + /* 470 */ 94, 93, 350, 99, 100, 90, 971, 971, 847, 850, + /* 480 */ 839, 839, 97, 97, 98, 98, 98, 98, 194, 316, + /* 490 */ 929, 401, 398, 397, 224, 224, 1265, 939, 353, 1318, + /* 500 */ 317, 324, 396, 1063, 1063, 813, 414, 1061, 1061, 950, + /* 510 */ 299, 448, 992, 268, 96, 96, 96, 96, 95, 95, + /* 520 */ 94, 94, 94, 93, 350, 99, 100, 90, 971, 971, + /* 530 */ 847, 850, 839, 839, 97, 97, 98, 98, 98, 98, + /* 540 */ 757, 1041, 449, 893, 893, 386, 950, 951, 952, 410, + /* 550 */ 992, 747, 747, 324, 229, 268, 221, 296, 268, 771, + /* 560 */ 890, 378, 52, 52, 890, 421, 96, 96, 96, 96, + /* 570 */ 95, 95, 94, 94, 94, 93, 350, 99, 100, 90, + /* 580 */ 971, 971, 847, 850, 839, 839, 97, 97, 98, 98, + /* 590 */ 98, 98, 103, 449, 275, 384, 1241, 343, 157, 1207, + /* 600 */ 909, 669, 670, 671, 176, 197, 196, 195, 324, 298, + /* 610 */ 319, 1266, 2, 37, 37, 910, 1134, 1040, 96, 96, + /* 620 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 697, + /* 630 */ 911, 177, 99, 100, 90, 971, 971, 847, 850, 839, + /* 640 */ 839, 97, 97, 98, 98, 98, 98, 230, 146, 120, + /* 650 */ 735, 1235, 826, 270, 1141, 273, 1141, 771, 171, 170, + /* 660 */ 736, 1141, 82, 324, 80, 268, 697, 819, 158, 268, + /* 670 */ 378, 818, 78, 96, 96, 96, 96, 95, 95, 94, + /* 680 */ 94, 94, 93, 350, 120, 950, 393, 99, 100, 90, + /* 690 */ 971, 971, 847, 850, 839, 839, 97, 97, 98, 98, + /* 700 */ 98, 98, 818, 818, 820, 1141, 1070, 370, 331, 133, + /* 710 */ 1066, 1141, 1250, 198, 268, 324, 1016, 330, 245, 333, + /* 720 */ 24, 334, 950, 951, 952, 368, 335, 81, 96, 96, + /* 730 */ 96, 96, 95, 95, 94, 94, 94, 93, 350, 99, + /* 740 */ 100, 90, 971, 971, 847, 850, 839, 839, 97, 97, + /* 750 */ 98, 98, 98, 98, 132, 267, 260, 445, 330, 223, + /* 760 */ 175, 1289, 925, 752, 724, 318, 1073, 324, 751, 246, + /* 770 */ 385, 301, 301, 378, 329, 361, 344, 414, 1233, 280, + /* 780 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, + /* 790 */ 350, 99, 88, 90, 971, 971, 847, 850, 839, 839, + /* 800 */ 97, 97, 98, 98, 98, 98, 337, 346, 721, 722, + /* 810 */ 449, 120, 118, 887, 162, 887, 810, 371, 324, 202, + /* 820 */ 202, 373, 249, 263, 202, 394, 74, 704, 208, 1069, + /* 830 */ 12, 12, 96, 96, 96, 96, 95, 95, 94, 94, + /* 840 */ 94, 93, 350, 100, 90, 971, 971, 847, 850, 839, + /* 850 */ 839, 97, 97, 98, 98, 98, 98, 449, 771, 232, + /* 860 */ 449, 278, 120, 286, 74, 704, 714, 713, 324, 342, + /* 870 */ 749, 877, 1209, 77, 285, 1255, 780, 52, 52, 202, + /* 880 */ 27, 27, 418, 96, 96, 96, 96, 95, 95, 94, + /* 890 */ 94, 94, 93, 350, 90, 971, 971, 847, 850, 839, + /* 900 */ 839, 97, 97, 98, 98, 98, 98, 86, 444, 877, + /* 910 */ 3, 1193, 422, 1013, 873, 435, 886, 208, 886, 689, + /* 920 */ 1091, 257, 116, 822, 447, 1230, 117, 1229, 86, 444, + /* 930 */ 177, 3, 381, 96, 96, 96, 96, 95, 95, 94, + /* 940 */ 94, 94, 93, 350, 339, 447, 120, 351, 120, 212, + /* 950 */ 169, 287, 404, 282, 403, 199, 771, 950, 433, 419, + /* 960 */ 439, 822, 280, 691, 1039, 264, 269, 132, 351, 153, + /* 970 */ 826, 376, 74, 272, 274, 276, 83, 84, 1054, 433, + /* 980 */ 147, 1038, 443, 85, 351, 451, 450, 281, 132, 818, + /* 990 */ 25, 826, 449, 120, 950, 951, 952, 83, 84, 86, + /* 1000 */ 444, 691, 3, 408, 85, 351, 451, 450, 449, 5, + /* 1010 */ 818, 203, 32, 32, 1107, 120, 447, 950, 225, 1140, + /* 1020 */ 818, 818, 820, 821, 19, 203, 226, 950, 38, 38, + /* 1030 */ 1087, 314, 314, 313, 215, 311, 120, 449, 678, 351, + /* 1040 */ 237, 818, 818, 820, 821, 19, 969, 409, 377, 1, + /* 1050 */ 433, 180, 706, 248, 950, 951, 952, 10, 10, 449, + /* 1060 */ 969, 247, 826, 1098, 950, 951, 952, 430, 83, 84, + /* 1070 */ 756, 336, 950, 20, 431, 85, 351, 451, 450, 10, + /* 1080 */ 10, 818, 86, 444, 969, 3, 950, 449, 302, 303, + /* 1090 */ 182, 950, 1146, 338, 1021, 1015, 1004, 183, 969, 447, + /* 1100 */ 132, 181, 76, 444, 21, 3, 449, 10, 10, 950, + /* 1110 */ 951, 952, 818, 818, 820, 821, 19, 715, 1279, 447, + /* 1120 */ 389, 233, 351, 950, 951, 952, 10, 10, 950, 951, + /* 1130 */ 952, 1003, 218, 433, 1005, 325, 1273, 773, 289, 291, + /* 1140 */ 424, 293, 351, 7, 159, 826, 363, 402, 315, 360, + /* 1150 */ 1129, 83, 84, 433, 1232, 716, 772, 259, 85, 351, + /* 1160 */ 451, 450, 358, 375, 818, 826, 360, 359, 399, 1211, + /* 1170 */ 157, 83, 84, 681, 98, 98, 98, 98, 85, 351, + /* 1180 */ 451, 450, 323, 252, 818, 295, 1211, 1213, 1235, 173, + /* 1190 */ 1037, 284, 434, 340, 1204, 818, 818, 820, 821, 19, + /* 1200 */ 308, 234, 449, 234, 96, 96, 96, 96, 95, 95, + /* 1210 */ 94, 94, 94, 93, 350, 818, 818, 820, 821, 19, + /* 1220 */ 909, 120, 39, 39, 1203, 449, 168, 360, 449, 1276, + /* 1230 */ 367, 449, 135, 449, 986, 910, 449, 1249, 449, 1247, + /* 1240 */ 449, 205, 983, 449, 370, 40, 40, 1211, 41, 41, + /* 1250 */ 911, 42, 42, 28, 28, 870, 29, 29, 31, 31, + /* 1260 */ 43, 43, 379, 44, 44, 449, 59, 449, 332, 449, + /* 1270 */ 432, 62, 144, 156, 449, 130, 449, 72, 449, 137, + /* 1280 */ 449, 365, 449, 392, 139, 45, 45, 11, 11, 46, + /* 1290 */ 46, 140, 1200, 449, 105, 105, 47, 47, 48, 48, + /* 1300 */ 33, 33, 49, 49, 1126, 449, 141, 366, 449, 185, + /* 1310 */ 142, 449, 1234, 50, 50, 449, 160, 449, 148, 449, + /* 1320 */ 1136, 382, 449, 67, 449, 34, 34, 449, 122, 122, + /* 1330 */ 449, 123, 123, 449, 1198, 124, 124, 56, 56, 35, + /* 1340 */ 35, 449, 106, 106, 53, 53, 449, 107, 107, 449, + /* 1350 */ 108, 108, 449, 104, 104, 449, 406, 449, 388, 449, + /* 1360 */ 189, 121, 121, 449, 190, 449, 119, 119, 449, 112, + /* 1370 */ 112, 449, 111, 111, 1218, 109, 109, 110, 110, 55, + /* 1380 */ 55, 266, 752, 57, 57, 54, 54, 751, 26, 26, + /* 1390 */ 1099, 30, 30, 219, 154, 390, 271, 191, 321, 1006, + /* 1400 */ 192, 405, 1057, 1056, 1055, 341, 1048, 706, 1047, 1029, + /* 1410 */ 322, 420, 1028, 71, 1095, 283, 288, 1027, 1288, 204, + /* 1420 */ 6, 297, 79, 1184, 437, 1096, 1094, 290, 345, 292, + /* 1430 */ 441, 1093, 294, 102, 425, 73, 423, 213, 1012, 22, + /* 1440 */ 452, 945, 214, 1077, 216, 217, 238, 453, 306, 304, + /* 1450 */ 307, 239, 240, 1001, 305, 125, 996, 126, 115, 235, + /* 1460 */ 127, 665, 352, 166, 244, 179, 356, 113, 885, 883, + /* 1470 */ 806, 136, 128, 738, 326, 138, 327, 258, 184, 899, + /* 1480 */ 143, 129, 145, 63, 64, 65, 66, 902, 186, 187, + /* 1490 */ 898, 8, 13, 188, 134, 265, 891, 202, 980, 387, + /* 1500 */ 150, 149, 680, 161, 391, 193, 285, 279, 395, 151, + /* 1510 */ 68, 717, 14, 15, 400, 69, 16, 131, 236, 825, + /* 1520 */ 824, 853, 746, 750, 4, 70, 174, 413, 220, 222, + /* 1530 */ 152, 779, 774, 77, 868, 74, 854, 201, 17, 852, + /* 1540 */ 908, 206, 907, 207, 18, 857, 934, 163, 436, 210, + /* 1550 */ 935, 164, 209, 165, 440, 856, 823, 312, 690, 87, + /* 1560 */ 211, 309, 1281, 940, 995, 1280, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 19, 115, 19, 117, 118, 24, 1, 2, 27, 79, - /* 10 */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - /* 20 */ 90, 91, 92, 93, 94, 144, 145, 146, 147, 58, - /* 30 */ 49, 50, 79, 80, 81, 82, 22, 84, 85, 86, - /* 40 */ 87, 88, 89, 90, 91, 92, 93, 94, 221, 222, - /* 50 */ 223, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 60 */ 79, 80, 81, 82, 94, 84, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 93, 94, 19, 94, 97, 108, - /* 80 */ 109, 110, 99, 100, 101, 102, 103, 104, 105, 32, - /* 90 */ 119, 120, 78, 27, 152, 112, 93, 94, 41, 88, - /* 100 */ 89, 90, 91, 92, 93, 94, 49, 50, 84, 85, - /* 110 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 58, - /* 120 */ 157, 119, 120, 163, 68, 163, 65, 70, 71, 72, - /* 130 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - /* 140 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 150 */ 93, 94, 19, 97, 88, 89, 196, 101, 196, 26, - /* 160 */ 172, 173, 96, 97, 98, 210, 100, 22, 152, 108, - /* 170 */ 109, 110, 27, 107, 27, 109, 221, 222, 223, 219, - /* 180 */ 238, 219, 49, 50, 152, 169, 170, 54, 132, 133, - /* 190 */ 134, 228, 232, 171, 231, 207, 208, 237, 132, 237, - /* 200 */ 134, 179, 19, 70, 71, 72, 73, 74, 75, 76, - /* 210 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86, - /* 220 */ 87, 88, 89, 90, 91, 92, 93, 94, 27, 65, - /* 230 */ 30, 152, 49, 50, 34, 52, 90, 91, 92, 93, - /* 240 */ 94, 96, 97, 98, 97, 22, 230, 27, 48, 217, - /* 250 */ 27, 172, 173, 70, 71, 72, 73, 74, 75, 76, - /* 260 */ 77, 78, 79, 80, 81, 82, 172, 84, 85, 86, - /* 270 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 148, - /* 280 */ 149, 152, 218, 24, 152, 154, 207, 156, 172, 152, - /* 290 */ 22, 68, 27, 152, 163, 27, 164, 96, 97, 98, - /* 300 */ 99, 172, 173, 102, 103, 104, 169, 170, 49, 50, - /* 310 */ 90, 88, 89, 152, 113, 186, 96, 97, 98, 96, - /* 320 */ 97, 160, 57, 27, 101, 164, 137, 196, 139, 70, - /* 330 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 340 */ 81, 82, 11, 84, 85, 86, 87, 88, 89, 90, - /* 350 */ 91, 92, 93, 94, 19, 132, 133, 134, 23, 218, - /* 360 */ 152, 96, 97, 98, 96, 97, 98, 230, 99, 22, - /* 370 */ 152, 102, 103, 104, 27, 244, 152, 152, 27, 26, - /* 380 */ 152, 22, 113, 65, 49, 50, 27, 194, 195, 58, - /* 390 */ 172, 173, 96, 97, 98, 185, 65, 172, 173, 206, - /* 400 */ 172, 173, 190, 191, 186, 70, 71, 72, 73, 74, - /* 410 */ 75, 76, 77, 78, 79, 80, 81, 82, 175, 84, - /* 420 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - /* 430 */ 19, 175, 207, 208, 23, 207, 208, 119, 120, 108, - /* 440 */ 109, 110, 27, 96, 97, 98, 116, 96, 97, 98, - /* 450 */ 152, 121, 152, 179, 180, 96, 97, 98, 250, 106, - /* 460 */ 49, 50, 188, 19, 221, 222, 223, 168, 169, 170, - /* 470 */ 172, 173, 172, 173, 250, 124, 172, 221, 222, 223, - /* 480 */ 26, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 490 */ 79, 80, 81, 82, 50, 84, 85, 86, 87, 88, - /* 500 */ 89, 90, 91, 92, 93, 94, 19, 207, 208, 12, - /* 510 */ 23, 96, 97, 98, 221, 222, 223, 194, 195, 152, - /* 520 */ 199, 23, 19, 225, 26, 28, 152, 152, 152, 206, - /* 530 */ 209, 164, 190, 191, 241, 152, 49, 50, 152, 124, - /* 540 */ 152, 44, 219, 46, 152, 21, 172, 173, 172, 173, - /* 550 */ 183, 107, 185, 16, 163, 58, 112, 70, 71, 72, - /* 560 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - /* 570 */ 152, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 580 */ 93, 94, 19, 207, 130, 152, 23, 196, 64, 152, - /* 590 */ 172, 173, 22, 152, 24, 152, 98, 27, 61, 96, - /* 600 */ 63, 26, 211, 212, 186, 172, 173, 49, 50, 172, - /* 610 */ 173, 23, 49, 50, 26, 172, 173, 88, 89, 186, - /* 620 */ 24, 238, 124, 27, 238, 22, 23, 103, 187, 26, - /* 630 */ 152, 73, 74, 70, 71, 72, 73, 74, 75, 76, - /* 640 */ 77, 78, 79, 80, 81, 82, 152, 84, 85, 86, - /* 650 */ 87, 88, 89, 90, 91, 92, 93, 94, 19, 101, - /* 660 */ 152, 132, 23, 134, 140, 152, 12, 97, 36, 168, - /* 670 */ 169, 170, 69, 98, 152, 22, 23, 140, 50, 26, - /* 680 */ 172, 173, 28, 51, 152, 172, 173, 193, 49, 50, - /* 690 */ 22, 59, 24, 97, 172, 173, 152, 152, 44, 124, - /* 700 */ 46, 0, 1, 2, 172, 173, 22, 23, 19, 70, - /* 710 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 720 */ 81, 82, 69, 84, 85, 86, 87, 88, 89, 90, - /* 730 */ 91, 92, 93, 94, 152, 107, 152, 193, 49, 50, - /* 740 */ 181, 22, 23, 111, 108, 109, 110, 7, 8, 9, - /* 750 */ 16, 247, 248, 69, 172, 173, 172, 173, 152, 70, - /* 760 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 770 */ 81, 82, 152, 84, 85, 86, 87, 88, 89, 90, - /* 780 */ 91, 92, 93, 94, 19, 152, 242, 152, 69, 152, - /* 790 */ 166, 167, 172, 173, 32, 61, 152, 63, 152, 193, - /* 800 */ 152, 152, 152, 41, 152, 172, 173, 172, 173, 172, - /* 810 */ 173, 152, 152, 152, 49, 50, 172, 173, 172, 173, - /* 820 */ 172, 173, 172, 173, 172, 173, 132, 138, 134, 152, - /* 830 */ 152, 172, 173, 172, 173, 70, 71, 72, 73, 74, - /* 840 */ 75, 76, 77, 78, 79, 80, 81, 82, 152, 84, - /* 850 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - /* 860 */ 19, 152, 22, 152, 195, 24, 152, 27, 172, 173, - /* 870 */ 193, 193, 152, 152, 152, 206, 152, 217, 152, 152, - /* 880 */ 152, 172, 173, 172, 173, 152, 172, 173, 152, 152, - /* 890 */ 49, 50, 172, 173, 172, 173, 172, 173, 172, 173, - /* 900 */ 172, 173, 152, 138, 152, 172, 173, 108, 109, 110, - /* 910 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 920 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, - /* 930 */ 89, 90, 91, 92, 93, 94, 152, 97, 152, 152, - /* 940 */ 49, 50, 26, 193, 172, 173, 152, 152, 152, 146, - /* 950 */ 147, 132, 152, 134, 217, 181, 172, 173, 172, 173, - /* 960 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 970 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, - /* 980 */ 89, 90, 91, 92, 93, 94, 152, 193, 152, 193, - /* 990 */ 49, 50, 181, 193, 172, 173, 166, 167, 245, 246, - /* 1000 */ 211, 212, 152, 22, 217, 152, 172, 173, 172, 173, - /* 1010 */ 19, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 1020 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, - /* 1030 */ 89, 90, 91, 92, 93, 94, 152, 187, 152, 123, - /* 1040 */ 49, 50, 23, 23, 23, 26, 26, 26, 23, 23, - /* 1050 */ 23, 26, 26, 26, 7, 8, 172, 173, 172, 173, - /* 1060 */ 19, 90, 71, 72, 73, 74, 75, 76, 77, 78, - /* 1070 */ 79, 80, 81, 82, 152, 84, 85, 86, 87, 88, - /* 1080 */ 89, 90, 91, 92, 93, 94, 152, 116, 152, 217, - /* 1090 */ 49, 50, 121, 23, 172, 173, 26, 100, 101, 27, - /* 1100 */ 101, 27, 23, 122, 152, 26, 172, 173, 172, 173, - /* 1110 */ 152, 112, 163, 72, 73, 74, 75, 76, 77, 78, - /* 1120 */ 79, 80, 81, 82, 163, 84, 85, 86, 87, 88, - /* 1130 */ 89, 90, 91, 92, 93, 94, 19, 20, 152, 22, - /* 1140 */ 23, 152, 163, 65, 27, 196, 163, 19, 20, 23, - /* 1150 */ 22, 213, 26, 19, 37, 27, 152, 196, 172, 173, - /* 1160 */ 152, 172, 173, 27, 23, 37, 152, 26, 152, 97, - /* 1170 */ 152, 97, 210, 56, 163, 196, 163, 163, 100, 196, - /* 1180 */ 172, 173, 65, 152, 56, 68, 172, 173, 172, 173, - /* 1190 */ 172, 173, 152, 65, 163, 163, 68, 23, 152, 234, - /* 1200 */ 26, 152, 152, 172, 173, 88, 89, 196, 152, 196, - /* 1210 */ 196, 152, 95, 96, 97, 98, 88, 89, 101, 152, - /* 1220 */ 152, 207, 208, 95, 96, 97, 98, 196, 196, 101, - /* 1230 */ 96, 233, 152, 97, 152, 152, 19, 20, 207, 22, - /* 1240 */ 152, 152, 152, 191, 27, 152, 152, 152, 152, 132, - /* 1250 */ 133, 134, 135, 136, 37, 152, 152, 152, 152, 152, - /* 1260 */ 132, 133, 134, 135, 136, 210, 197, 210, 210, 198, - /* 1270 */ 150, 184, 239, 56, 201, 214, 214, 201, 239, 180, - /* 1280 */ 214, 227, 198, 38, 176, 68, 175, 175, 175, 122, - /* 1290 */ 155, 200, 159, 19, 20, 40, 22, 159, 159, 22, - /* 1300 */ 70, 27, 130, 243, 240, 88, 89, 90, 189, 18, - /* 1310 */ 201, 37, 95, 96, 97, 98, 192, 5, 101, 192, - /* 1320 */ 220, 240, 10, 11, 12, 13, 14, 159, 18, 17, - /* 1330 */ 56, 158, 192, 201, 192, 220, 189, 189, 201, 159, - /* 1340 */ 158, 137, 68, 31, 45, 33, 236, 159, 159, 132, - /* 1350 */ 133, 134, 135, 136, 42, 158, 235, 22, 177, 159, - /* 1360 */ 158, 158, 88, 89, 159, 107, 174, 55, 177, 95, - /* 1370 */ 96, 97, 98, 174, 62, 101, 47, 65, 66, 106, - /* 1380 */ 174, 125, 19, 20, 174, 22, 177, 176, 174, 182, - /* 1390 */ 27, 216, 174, 174, 182, 107, 159, 22, 215, 215, - /* 1400 */ 37, 216, 216, 216, 137, 215, 132, 133, 134, 135, - /* 1410 */ 136, 215, 159, 177, 94, 177, 129, 224, 205, 56, - /* 1420 */ 226, 126, 128, 203, 229, 204, 114, 229, 127, 202, - /* 1430 */ 201, 68, 25, 162, 26, 13, 161, 153, 153, 6, - /* 1440 */ 151, 151, 178, 151, 151, 165, 165, 178, 165, 4, - /* 1450 */ 249, 88, 89, 141, 3, 142, 22, 249, 95, 96, - /* 1460 */ 97, 98, 246, 15, 101, 67, 16, 23, 120, 23, - /* 1470 */ 131, 111, 123, 20, 16, 125, 1, 123, 131, 78, - /* 1480 */ 78, 78, 78, 111, 96, 1, 122, 35, 5, 22, - /* 1490 */ 107, 140, 53, 53, 26, 132, 133, 134, 135, 136, - /* 1500 */ 43, 60, 107, 24, 112, 20, 19, 52, 22, 29, - /* 1510 */ 105, 22, 22, 52, 23, 22, 22, 52, 23, 23, - /* 1520 */ 39, 23, 116, 26, 22, 26, 23, 22, 96, 23, - /* 1530 */ 23, 122, 22, 24, 124, 35, 35, 26, 26, 35, - /* 1540 */ 23, 23, 23, 23, 11, 23, 22, 26, 23, 22, - /* 1550 */ 122, 23, 26, 22, 24, 23, 22, 122, 23, 23, - /* 1560 */ 22, 15, 23, 1, 122, 122, + /* 0 */ 19, 144, 145, 146, 147, 24, 90, 91, 92, 93, + /* 10 */ 94, 54, 55, 56, 57, 58, 88, 89, 90, 91, + /* 20 */ 92, 93, 94, 152, 43, 44, 45, 46, 47, 48, + /* 30 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 94, + /* 40 */ 59, 84, 85, 86, 87, 88, 89, 90, 91, 92, + /* 50 */ 93, 94, 59, 84, 85, 86, 87, 88, 89, 90, + /* 60 */ 91, 92, 93, 94, 193, 84, 85, 86, 87, 88, + /* 70 */ 89, 90, 91, 92, 93, 94, 194, 195, 97, 79, + /* 80 */ 11, 88, 89, 152, 26, 19, 171, 152, 206, 96, + /* 90 */ 97, 98, 72, 100, 179, 59, 152, 31, 163, 79, + /* 100 */ 107, 219, 109, 172, 173, 39, 79, 172, 173, 43, + /* 110 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 120 */ 54, 55, 56, 57, 152, 132, 199, 134, 108, 109, + /* 130 */ 110, 196, 96, 97, 98, 99, 209, 19, 102, 103, + /* 140 */ 104, 72, 207, 208, 26, 72, 119, 120, 79, 113, + /* 150 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 160 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 170 */ 52, 53, 54, 55, 56, 57, 31, 108, 109, 110, + /* 180 */ 82, 108, 109, 110, 39, 210, 68, 175, 130, 19, + /* 190 */ 218, 175, 119, 120, 250, 97, 221, 222, 223, 101, + /* 200 */ 172, 152, 84, 85, 86, 87, 88, 89, 90, 91, + /* 210 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, + /* 220 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 152, + /* 230 */ 132, 133, 134, 221, 222, 223, 66, 221, 222, 223, + /* 240 */ 172, 19, 193, 22, 23, 152, 24, 26, 172, 173, + /* 250 */ 46, 47, 48, 49, 84, 85, 86, 87, 88, 89, + /* 260 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, + /* 270 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 280 */ 221, 222, 223, 207, 208, 46, 22, 23, 148, 149, + /* 290 */ 26, 242, 172, 19, 154, 218, 156, 23, 88, 89, + /* 300 */ 241, 59, 163, 163, 83, 101, 84, 85, 86, 87, + /* 310 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, + /* 320 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 330 */ 56, 57, 152, 157, 152, 196, 196, 16, 96, 97, + /* 340 */ 98, 26, 132, 250, 134, 19, 107, 83, 59, 23, + /* 350 */ 211, 212, 172, 173, 172, 173, 1, 2, 84, 85, + /* 360 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, + /* 370 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 380 */ 54, 55, 56, 57, 244, 152, 97, 207, 208, 207, + /* 390 */ 208, 185, 221, 222, 223, 152, 75, 19, 77, 179, + /* 400 */ 180, 23, 93, 94, 228, 172, 173, 231, 188, 152, + /* 410 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 420 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 430 */ 52, 53, 54, 55, 56, 57, 193, 152, 123, 152, + /* 440 */ 207, 208, 152, 168, 169, 170, 168, 169, 170, 19, + /* 450 */ 160, 22, 23, 23, 164, 119, 120, 172, 173, 172, + /* 460 */ 173, 140, 84, 85, 86, 87, 88, 89, 90, 91, + /* 470 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, + /* 480 */ 50, 51, 52, 53, 54, 55, 56, 57, 99, 22, + /* 490 */ 23, 102, 103, 104, 194, 195, 0, 1, 2, 247, + /* 500 */ 248, 19, 113, 190, 191, 23, 206, 190, 191, 59, + /* 510 */ 225, 152, 83, 152, 84, 85, 86, 87, 88, 89, + /* 520 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, + /* 530 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 540 */ 90, 181, 152, 108, 109, 110, 96, 97, 98, 115, + /* 550 */ 83, 117, 118, 19, 193, 152, 23, 152, 152, 26, + /* 560 */ 29, 152, 172, 173, 33, 152, 84, 85, 86, 87, + /* 570 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, + /* 580 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 590 */ 56, 57, 22, 152, 16, 64, 193, 207, 152, 193, + /* 600 */ 12, 7, 8, 9, 152, 108, 109, 110, 19, 152, + /* 610 */ 164, 146, 147, 172, 173, 27, 163, 181, 84, 85, + /* 620 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 59, + /* 630 */ 42, 98, 43, 44, 45, 46, 47, 48, 49, 50, + /* 640 */ 51, 52, 53, 54, 55, 56, 57, 238, 22, 196, + /* 650 */ 62, 163, 82, 75, 152, 77, 152, 124, 88, 89, + /* 660 */ 72, 152, 137, 19, 139, 152, 96, 97, 24, 152, + /* 670 */ 152, 101, 138, 84, 85, 86, 87, 88, 89, 90, + /* 680 */ 91, 92, 93, 94, 196, 59, 19, 43, 44, 45, + /* 690 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 700 */ 56, 57, 132, 133, 134, 152, 193, 219, 245, 246, + /* 710 */ 193, 152, 152, 46, 152, 19, 166, 167, 152, 217, + /* 720 */ 232, 217, 96, 97, 98, 237, 217, 138, 84, 85, + /* 730 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, + /* 740 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 750 */ 54, 55, 56, 57, 79, 193, 238, 166, 167, 211, + /* 760 */ 212, 23, 23, 116, 26, 26, 195, 19, 121, 152, + /* 770 */ 217, 152, 152, 152, 107, 100, 217, 206, 163, 112, + /* 780 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 790 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 800 */ 52, 53, 54, 55, 56, 57, 187, 187, 7, 8, + /* 810 */ 152, 196, 22, 132, 24, 134, 23, 23, 19, 26, + /* 820 */ 26, 23, 152, 23, 26, 23, 26, 59, 26, 163, + /* 830 */ 172, 173, 84, 85, 86, 87, 88, 89, 90, 91, + /* 840 */ 92, 93, 94, 44, 45, 46, 47, 48, 49, 50, + /* 850 */ 51, 52, 53, 54, 55, 56, 57, 152, 26, 238, + /* 860 */ 152, 23, 196, 101, 26, 97, 100, 101, 19, 19, + /* 870 */ 23, 59, 152, 26, 112, 152, 23, 172, 173, 26, + /* 880 */ 172, 173, 19, 84, 85, 86, 87, 88, 89, 90, + /* 890 */ 91, 92, 93, 94, 45, 46, 47, 48, 49, 50, + /* 900 */ 51, 52, 53, 54, 55, 56, 57, 19, 20, 97, + /* 910 */ 22, 23, 207, 163, 23, 163, 132, 26, 134, 23, + /* 920 */ 213, 152, 26, 59, 36, 152, 22, 152, 19, 20, + /* 930 */ 98, 22, 152, 84, 85, 86, 87, 88, 89, 90, + /* 940 */ 91, 92, 93, 94, 94, 36, 196, 59, 196, 99, + /* 950 */ 100, 101, 102, 103, 104, 105, 124, 59, 70, 96, + /* 960 */ 163, 97, 112, 59, 181, 152, 152, 79, 59, 71, + /* 970 */ 82, 19, 26, 152, 152, 152, 88, 89, 152, 70, + /* 980 */ 22, 152, 163, 95, 96, 97, 98, 152, 79, 101, + /* 990 */ 22, 82, 152, 196, 96, 97, 98, 88, 89, 19, + /* 1000 */ 20, 97, 22, 163, 95, 96, 97, 98, 152, 22, + /* 1010 */ 101, 24, 172, 173, 152, 196, 36, 59, 22, 152, + /* 1020 */ 132, 133, 134, 135, 136, 24, 5, 59, 172, 173, + /* 1030 */ 152, 10, 11, 12, 13, 14, 196, 152, 17, 59, + /* 1040 */ 210, 132, 133, 134, 135, 136, 59, 207, 96, 22, + /* 1050 */ 70, 30, 106, 32, 96, 97, 98, 172, 173, 152, + /* 1060 */ 59, 40, 82, 152, 96, 97, 98, 152, 88, 89, + /* 1070 */ 90, 186, 59, 22, 191, 95, 96, 97, 98, 172, + /* 1080 */ 173, 101, 19, 20, 97, 22, 59, 152, 152, 152, + /* 1090 */ 69, 59, 152, 186, 152, 152, 152, 76, 97, 36, + /* 1100 */ 79, 80, 19, 20, 53, 22, 152, 172, 173, 96, + /* 1110 */ 97, 98, 132, 133, 134, 135, 136, 35, 122, 36, + /* 1120 */ 234, 186, 59, 96, 97, 98, 172, 173, 96, 97, + /* 1130 */ 98, 152, 233, 70, 152, 114, 152, 124, 210, 210, + /* 1140 */ 186, 210, 59, 198, 197, 82, 214, 65, 150, 152, + /* 1150 */ 201, 88, 89, 70, 201, 73, 124, 239, 95, 96, + /* 1160 */ 97, 98, 141, 239, 101, 82, 169, 170, 176, 152, + /* 1170 */ 152, 88, 89, 21, 54, 55, 56, 57, 95, 96, + /* 1180 */ 97, 98, 164, 214, 101, 214, 169, 170, 163, 184, + /* 1190 */ 180, 175, 227, 111, 175, 132, 133, 134, 135, 136, + /* 1200 */ 200, 183, 152, 185, 84, 85, 86, 87, 88, 89, + /* 1210 */ 90, 91, 92, 93, 94, 132, 133, 134, 135, 136, + /* 1220 */ 12, 196, 172, 173, 175, 152, 198, 230, 152, 155, + /* 1230 */ 78, 152, 243, 152, 60, 27, 152, 159, 152, 159, + /* 1240 */ 152, 122, 38, 152, 219, 172, 173, 230, 172, 173, + /* 1250 */ 42, 172, 173, 172, 173, 103, 172, 173, 172, 173, + /* 1260 */ 172, 173, 237, 172, 173, 152, 240, 152, 159, 152, + /* 1270 */ 62, 240, 22, 220, 152, 43, 152, 130, 152, 189, + /* 1280 */ 152, 18, 152, 18, 192, 172, 173, 172, 173, 172, + /* 1290 */ 173, 192, 140, 152, 172, 173, 172, 173, 172, 173, + /* 1300 */ 172, 173, 172, 173, 201, 152, 192, 159, 152, 158, + /* 1310 */ 192, 152, 201, 172, 173, 152, 220, 152, 189, 152, + /* 1320 */ 189, 159, 152, 137, 152, 172, 173, 152, 172, 173, + /* 1330 */ 152, 172, 173, 152, 201, 172, 173, 172, 173, 172, + /* 1340 */ 173, 152, 172, 173, 172, 173, 152, 172, 173, 152, + /* 1350 */ 172, 173, 152, 172, 173, 152, 90, 152, 61, 152, + /* 1360 */ 158, 172, 173, 152, 158, 152, 172, 173, 152, 172, + /* 1370 */ 173, 152, 172, 173, 236, 172, 173, 172, 173, 172, + /* 1380 */ 173, 235, 116, 172, 173, 172, 173, 121, 172, 173, + /* 1390 */ 159, 172, 173, 159, 22, 177, 159, 158, 177, 159, + /* 1400 */ 158, 107, 174, 174, 174, 63, 182, 106, 182, 174, + /* 1410 */ 177, 125, 176, 107, 216, 174, 215, 174, 174, 159, + /* 1420 */ 22, 159, 137, 224, 177, 216, 216, 215, 94, 215, + /* 1430 */ 177, 216, 215, 129, 126, 128, 127, 25, 162, 26, + /* 1440 */ 161, 13, 153, 205, 153, 6, 226, 151, 202, 204, + /* 1450 */ 201, 229, 229, 151, 203, 165, 151, 165, 178, 178, + /* 1460 */ 165, 4, 3, 22, 142, 15, 81, 16, 23, 23, + /* 1470 */ 120, 131, 111, 20, 249, 123, 249, 16, 125, 1, + /* 1480 */ 123, 111, 131, 53, 53, 53, 53, 96, 34, 122, + /* 1490 */ 1, 5, 22, 107, 246, 140, 67, 26, 74, 41, + /* 1500 */ 107, 67, 20, 24, 19, 105, 112, 23, 66, 22, + /* 1510 */ 22, 28, 22, 22, 66, 22, 22, 37, 66, 23, + /* 1520 */ 23, 23, 116, 23, 22, 26, 122, 26, 23, 23, + /* 1530 */ 22, 96, 124, 26, 23, 26, 23, 34, 34, 23, + /* 1540 */ 23, 26, 23, 22, 34, 11, 23, 22, 24, 122, + /* 1550 */ 23, 22, 26, 22, 24, 23, 23, 15, 23, 22, + /* 1560 */ 122, 23, 122, 1, 251, 122, }; #define YY_SHIFT_USE_DFLT (1566) -#define YY_SHIFT_COUNT (455) -#define YY_SHIFT_MIN (-114) +#define YY_SHIFT_COUNT (454) +#define YY_SHIFT_MIN (-84) #define YY_SHIFT_MAX (1562) static const short yy_shift_ofst[] = { - /* 0 */ 5, 1117, 1312, 1128, 1274, 1274, 1274, 1274, 61, -19, - /* 10 */ 57, 57, 183, 1274, 1274, 1274, 1274, 1274, 1274, 1274, - /* 20 */ 66, 66, 201, -29, 331, 318, 133, 259, 335, 411, - /* 30 */ 487, 563, 639, 689, 765, 841, 891, 891, 891, 891, - /* 40 */ 891, 891, 891, 891, 891, 891, 891, 891, 891, 891, - /* 50 */ 891, 891, 891, 941, 891, 991, 1041, 1041, 1217, 1274, - /* 60 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, - /* 70 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, - /* 80 */ 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, - /* 90 */ 1363, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, 1274, - /* 100 */ 1274, 1274, 1274, 1274, -70, -47, -47, -47, -47, -47, - /* 110 */ 24, 11, 146, 296, 524, 444, 529, 529, 296, 3, - /* 120 */ 2, -30, 1566, 1566, 1566, -17, -17, -17, 145, 145, - /* 130 */ 497, 497, 265, 603, 653, 296, 296, 296, 296, 296, - /* 140 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - /* 150 */ 296, 296, 296, 296, 296, 701, 1078, 147, 147, 2, - /* 160 */ 164, 164, 164, 164, 164, 164, 1566, 1566, 1566, 223, - /* 170 */ 56, 56, 268, 269, 220, 347, 351, 415, 359, 296, - /* 180 */ 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, - /* 190 */ 296, 296, 296, 296, 296, 632, 632, 632, 296, 296, - /* 200 */ 498, 296, 296, 296, 570, 296, 296, 654, 296, 296, - /* 210 */ 296, 296, 296, 296, 296, 296, 296, 296, 636, 200, - /* 220 */ 596, 596, 596, 575, -114, 971, 740, 454, 503, 503, - /* 230 */ 1134, 454, 1134, 353, 588, 628, 762, 503, 189, 762, - /* 240 */ 762, 916, 330, 668, 1245, 1167, 1167, 1255, 1255, 1167, - /* 250 */ 1277, 1230, 1172, 1291, 1291, 1291, 1291, 1167, 1310, 1172, - /* 260 */ 1277, 1230, 1230, 1172, 1167, 1310, 1204, 1299, 1167, 1167, - /* 270 */ 1310, 1335, 1167, 1310, 1167, 1310, 1335, 1258, 1258, 1258, - /* 280 */ 1329, 1335, 1258, 1273, 1258, 1329, 1258, 1258, 1256, 1288, - /* 290 */ 1256, 1288, 1256, 1288, 1256, 1288, 1167, 1375, 1167, 1267, - /* 300 */ 1335, 1320, 1320, 1335, 1287, 1295, 1294, 1301, 1172, 1407, - /* 310 */ 1408, 1422, 1422, 1433, 1433, 1433, 1433, 1566, 1566, 1566, - /* 320 */ 1566, 1566, 1566, 1566, 1566, 558, 537, 684, 719, 734, - /* 330 */ 799, 840, 1019, 14, 1020, 1021, 1025, 1026, 1027, 1070, - /* 340 */ 1072, 997, 1047, 999, 1079, 1126, 1074, 1141, 694, 819, - /* 350 */ 1174, 1136, 981, 1445, 1451, 1434, 1313, 1448, 1398, 1450, - /* 360 */ 1444, 1446, 1348, 1339, 1360, 1349, 1453, 1350, 1458, 1475, - /* 370 */ 1354, 1347, 1401, 1402, 1403, 1404, 1372, 1388, 1452, 1364, - /* 380 */ 1484, 1483, 1467, 1383, 1351, 1439, 1468, 1440, 1441, 1457, - /* 390 */ 1395, 1479, 1485, 1487, 1392, 1405, 1486, 1455, 1489, 1490, - /* 400 */ 1491, 1493, 1461, 1480, 1494, 1465, 1481, 1495, 1496, 1498, - /* 410 */ 1497, 1406, 1502, 1503, 1505, 1499, 1409, 1506, 1507, 1432, - /* 420 */ 1500, 1510, 1410, 1511, 1501, 1512, 1504, 1517, 1511, 1518, - /* 430 */ 1519, 1520, 1521, 1522, 1524, 1533, 1525, 1527, 1509, 1526, - /* 440 */ 1528, 1531, 1530, 1526, 1532, 1534, 1535, 1536, 1538, 1428, - /* 450 */ 1435, 1442, 1443, 1539, 1546, 1562, + /* 0 */ 355, 888, 1021, 909, 1063, 1063, 1063, 1063, 20, -19, + /* 10 */ 66, 66, 170, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 20 */ -7, -7, 36, 73, 69, 27, 118, 222, 274, 326, + /* 30 */ 378, 430, 482, 534, 589, 644, 696, 696, 696, 696, + /* 40 */ 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + /* 50 */ 696, 696, 696, 748, 696, 799, 849, 849, 980, 1063, + /* 60 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 70 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 80 */ 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 90 */ 1083, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + /* 100 */ 1063, 1063, 1063, 1063, -43, 1120, 1120, 1120, 1120, 1120, + /* 110 */ -31, -72, -84, 242, 1152, 667, 210, 210, 242, 309, + /* 120 */ 336, -55, 1566, 1566, 1566, 850, 850, 850, 626, 626, + /* 130 */ 588, 588, 898, 221, 264, 242, 242, 242, 242, 242, + /* 140 */ 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + /* 150 */ 242, 242, 242, 242, 242, 496, 675, 289, 289, 336, + /* 160 */ 0, 0, 0, 0, 0, 0, 1566, 1566, 1566, 570, + /* 170 */ 98, 98, 958, 389, 450, 968, 1013, 1032, 1027, 242, + /* 180 */ 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + /* 190 */ 242, 242, 242, 242, 242, 1082, 1082, 1082, 242, 242, + /* 200 */ 533, 242, 242, 242, 987, 242, 242, 1208, 242, 242, + /* 210 */ 242, 242, 242, 242, 242, 242, 242, 242, 435, 531, + /* 220 */ 1001, 1001, 1001, 832, 434, 1266, 594, 58, 863, 863, + /* 230 */ 952, 58, 952, 946, 738, 239, 145, 863, 525, 145, + /* 240 */ 145, 315, 647, 790, 1174, 1119, 1119, 1204, 1204, 1119, + /* 250 */ 1250, 1232, 1147, 1263, 1263, 1263, 1263, 1119, 1265, 1147, + /* 260 */ 1250, 1232, 1232, 1147, 1119, 1265, 1186, 1297, 1119, 1119, + /* 270 */ 1265, 1372, 1119, 1265, 1119, 1265, 1372, 1294, 1294, 1294, + /* 280 */ 1342, 1372, 1294, 1301, 1294, 1342, 1294, 1294, 1286, 1306, + /* 290 */ 1286, 1306, 1286, 1306, 1286, 1306, 1119, 1398, 1119, 1285, + /* 300 */ 1372, 1334, 1334, 1372, 1304, 1308, 1307, 1309, 1147, 1412, + /* 310 */ 1413, 1428, 1428, 1439, 1439, 1439, 1566, 1566, 1566, 1566, + /* 320 */ 1566, 1566, 1566, 1566, 204, 321, 429, 467, 578, 497, + /* 330 */ 904, 739, 1051, 793, 794, 798, 800, 802, 838, 768, + /* 340 */ 766, 801, 762, 847, 853, 812, 891, 681, 784, 896, + /* 350 */ 864, 996, 1457, 1459, 1441, 1322, 1450, 1385, 1451, 1445, + /* 360 */ 1446, 1350, 1340, 1361, 1352, 1453, 1353, 1461, 1478, 1357, + /* 370 */ 1351, 1430, 1431, 1432, 1433, 1370, 1391, 1454, 1367, 1489, + /* 380 */ 1486, 1470, 1386, 1355, 1429, 1471, 1434, 1424, 1458, 1393, + /* 390 */ 1479, 1482, 1485, 1394, 1400, 1487, 1442, 1488, 1490, 1484, + /* 400 */ 1491, 1448, 1483, 1493, 1452, 1480, 1496, 1497, 1498, 1499, + /* 410 */ 1406, 1494, 1500, 1502, 1501, 1404, 1505, 1506, 1435, 1503, + /* 420 */ 1508, 1408, 1507, 1504, 1509, 1510, 1511, 1507, 1513, 1516, + /* 430 */ 1517, 1515, 1519, 1521, 1534, 1523, 1525, 1524, 1526, 1527, + /* 440 */ 1529, 1530, 1526, 1532, 1531, 1533, 1535, 1537, 1427, 1438, + /* 450 */ 1440, 1443, 1538, 1542, 1562, }; -#define YY_REDUCE_USE_DFLT (-174) -#define YY_REDUCE_COUNT (324) -#define YY_REDUCE_MIN (-173) -#define YY_REDUCE_MAX (1293) +#define YY_REDUCE_USE_DFLT (-144) +#define YY_REDUCE_COUNT (323) +#define YY_REDUCE_MIN (-143) +#define YY_REDUCE_MAX (1305) static const short yy_reduce_ofst[] = { - /* 0 */ -119, 1014, 131, 1031, -12, 225, 228, 300, -40, -45, - /* 10 */ 243, 256, 293, 129, 218, 418, 79, 376, 433, 298, - /* 20 */ 16, 137, 367, 323, -38, 391, -173, -173, -173, -173, - /* 30 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173, - /* 40 */ -173, -173, -173, -173, -173, -173, -173, -173, -173, -173, - /* 50 */ -173, -173, -173, -173, -173, -173, -173, -173, 374, 437, - /* 60 */ 443, 508, 513, 522, 532, 582, 584, 620, 633, 635, - /* 70 */ 637, 644, 646, 648, 650, 652, 659, 661, 696, 709, - /* 80 */ 711, 714, 720, 722, 724, 726, 728, 733, 772, 784, - /* 90 */ 786, 822, 834, 836, 884, 886, 922, 934, 936, 986, - /* 100 */ 989, 1008, 1016, 1018, -173, -173, -173, -173, -173, -173, - /* 110 */ -173, -173, -173, 544, -37, 274, 299, 501, 161, -173, - /* 120 */ 193, -173, -173, -173, -173, 22, 22, 22, 64, 141, - /* 130 */ 212, 342, 208, 504, 504, 132, 494, 606, 677, 678, - /* 140 */ 750, 794, 796, -58, 32, 383, 660, 737, 386, 787, - /* 150 */ 800, 441, 872, 224, 850, 803, 949, 624, 830, 669, - /* 160 */ 961, 979, 983, 1011, 1013, 1032, 753, 789, 321, 94, - /* 170 */ 116, 304, 375, 210, 388, 392, 478, 545, 649, 721, - /* 180 */ 727, 736, 752, 795, 853, 952, 958, 1004, 1040, 1046, - /* 190 */ 1049, 1050, 1056, 1059, 1067, 559, 774, 811, 1068, 1080, - /* 200 */ 938, 1082, 1083, 1088, 962, 1089, 1090, 1052, 1093, 1094, - /* 210 */ 1095, 388, 1096, 1103, 1104, 1105, 1106, 1107, 965, 998, - /* 220 */ 1055, 1057, 1058, 938, 1069, 1071, 1120, 1073, 1061, 1062, - /* 230 */ 1033, 1076, 1039, 1108, 1087, 1099, 1111, 1066, 1054, 1112, - /* 240 */ 1113, 1091, 1084, 1135, 1060, 1133, 1138, 1064, 1081, 1139, - /* 250 */ 1100, 1119, 1109, 1124, 1127, 1140, 1142, 1168, 1173, 1132, - /* 260 */ 1115, 1147, 1148, 1137, 1180, 1182, 1110, 1121, 1188, 1189, - /* 270 */ 1197, 1181, 1200, 1202, 1205, 1203, 1191, 1192, 1199, 1206, - /* 280 */ 1207, 1209, 1210, 1211, 1214, 1212, 1218, 1219, 1175, 1183, - /* 290 */ 1185, 1184, 1186, 1190, 1187, 1196, 1237, 1193, 1253, 1194, - /* 300 */ 1236, 1195, 1198, 1238, 1213, 1221, 1220, 1227, 1229, 1271, - /* 310 */ 1275, 1284, 1285, 1289, 1290, 1292, 1293, 1201, 1208, 1216, - /* 320 */ 1280, 1281, 1264, 1269, 1283, + /* 0 */ -143, -65, 140, 840, 76, 180, 182, 233, 488, -25, + /* 10 */ 12, 16, 59, 885, 907, 935, 390, 705, 954, 285, + /* 20 */ 997, 1017, 1018, -118, 1025, 139, 171, 171, 171, 171, + /* 30 */ 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + /* 40 */ 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + /* 50 */ 171, 171, 171, 171, 171, 171, 171, 171, -69, 287, + /* 60 */ 441, 658, 708, 856, 1050, 1073, 1076, 1079, 1081, 1084, + /* 70 */ 1086, 1088, 1091, 1113, 1115, 1117, 1122, 1124, 1126, 1128, + /* 80 */ 1130, 1141, 1153, 1156, 1159, 1163, 1165, 1167, 1170, 1172, + /* 90 */ 1175, 1178, 1181, 1189, 1194, 1197, 1200, 1203, 1205, 1207, + /* 100 */ 1211, 1213, 1216, 1219, 171, 171, 171, 171, 171, 171, + /* 110 */ 171, 171, 171, 49, 176, 220, 275, 278, 290, 171, + /* 120 */ 300, 171, 171, 171, 171, -85, -85, -85, -28, 77, + /* 130 */ 313, 317, -56, 252, 252, 446, -129, 243, 361, 403, + /* 140 */ 406, 513, 517, 409, 502, 518, 504, 509, 621, 553, + /* 150 */ 562, 619, 559, 93, 620, 465, 453, 550, 591, 571, + /* 160 */ 615, 666, 750, 752, 797, 819, 463, 548, -73, 28, + /* 170 */ 68, 120, 257, 206, 359, 405, 413, 452, 457, 560, + /* 180 */ 566, 617, 670, 720, 723, 769, 773, 775, 780, 813, + /* 190 */ 814, 821, 822, 823, 826, 360, 436, 783, 829, 835, + /* 200 */ 707, 862, 867, 878, 830, 911, 915, 883, 936, 937, + /* 210 */ 940, 359, 942, 943, 944, 979, 982, 984, 886, 899, + /* 220 */ 928, 929, 931, 707, 947, 945, 998, 949, 932, 969, + /* 230 */ 918, 953, 924, 992, 1005, 1010, 1016, 971, 965, 1019, + /* 240 */ 1049, 1000, 1028, 1074, 989, 1078, 1080, 1026, 1031, 1109, + /* 250 */ 1053, 1090, 1103, 1092, 1099, 1114, 1118, 1148, 1151, 1111, + /* 260 */ 1096, 1129, 1131, 1133, 1162, 1202, 1138, 1146, 1231, 1234, + /* 270 */ 1206, 1218, 1237, 1239, 1240, 1242, 1221, 1228, 1229, 1230, + /* 280 */ 1224, 1233, 1235, 1236, 1241, 1226, 1243, 1244, 1198, 1201, + /* 290 */ 1209, 1212, 1210, 1214, 1215, 1217, 1260, 1199, 1262, 1220, + /* 300 */ 1247, 1222, 1223, 1253, 1238, 1245, 1251, 1246, 1249, 1276, + /* 310 */ 1279, 1289, 1291, 1296, 1302, 1305, 1225, 1227, 1248, 1290, + /* 320 */ 1292, 1280, 1281, 1295, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1280, 1270, 1270, 1270, 1202, 1202, 1202, 1202, 1270, 1096, - /* 10 */ 1125, 1125, 1254, 1332, 1332, 1332, 1332, 1332, 1332, 1201, - /* 20 */ 1332, 1332, 1332, 1332, 1270, 1100, 1131, 1332, 1332, 1332, - /* 30 */ 1332, 1203, 1204, 1332, 1332, 1332, 1253, 1255, 1141, 1140, - /* 40 */ 1139, 1138, 1236, 1112, 1136, 1129, 1133, 1203, 1197, 1198, - /* 50 */ 1196, 1200, 1204, 1332, 1132, 1167, 1181, 1166, 1332, 1332, - /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 100 */ 1332, 1332, 1332, 1332, 1175, 1180, 1187, 1179, 1176, 1169, - /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, - /* 120 */ 1332, 1173, 1184, 1183, 1182, 1261, 1288, 1287, 1332, 1332, - /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 150 */ 1332, 1332, 1332, 1332, 1332, 1280, 1270, 1025, 1025, 1332, - /* 160 */ 1270, 1270, 1270, 1270, 1270, 1270, 1266, 1100, 1091, 1332, - /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 180 */ 1258, 1256, 1332, 1217, 1332, 1332, 1332, 1332, 1332, 1332, - /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, - /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1282, 1332, 1231, - /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, - /* 230 */ 1321, 1135, 1321, 1042, 1302, 1039, 1125, 1114, 1199, 1125, - /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, - /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, - /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1235, 1318, 1105, 1105, - /* 270 */ 1016, 1210, 1105, 1016, 1105, 1016, 1210, 1068, 1068, 1068, - /* 280 */ 1057, 1210, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, - /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1205, 1105, 1332, - /* 300 */ 1210, 1214, 1214, 1210, 1130, 1119, 1128, 1126, 1135, 1022, - /* 310 */ 1060, 1285, 1285, 1281, 1281, 1281, 1281, 1329, 1329, 1266, - /* 320 */ 1297, 1297, 1044, 1044, 1297, 1332, 1332, 1332, 1332, 1332, - /* 330 */ 1332, 1292, 1332, 1219, 1332, 1332, 1332, 1332, 1332, 1332, - /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 350 */ 1332, 1332, 1152, 1332, 1000, 1263, 1332, 1332, 1262, 1332, - /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, - /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1234, 1233, 1332, 1332, - /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 410 */ 1332, 1082, 1332, 1332, 1332, 1306, 1332, 1332, 1332, 1332, - /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, - /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1272, - /* 440 */ 1332, 1332, 1332, 1271, 1332, 1332, 1332, 1332, 1332, 1154, - /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, + /* 0 */ 1270, 1260, 1260, 1260, 1193, 1193, 1193, 1193, 1260, 1088, + /* 10 */ 1117, 1117, 1244, 1322, 1322, 1322, 1322, 1322, 1322, 1192, + /* 20 */ 1322, 1322, 1322, 1322, 1260, 1092, 1123, 1322, 1322, 1322, + /* 30 */ 1322, 1194, 1195, 1322, 1322, 1322, 1243, 1245, 1133, 1132, + /* 40 */ 1131, 1130, 1226, 1104, 1128, 1121, 1125, 1194, 1188, 1189, + /* 50 */ 1187, 1191, 1195, 1322, 1124, 1158, 1172, 1157, 1322, 1322, + /* 60 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 70 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 80 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 90 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 100 */ 1322, 1322, 1322, 1322, 1166, 1171, 1178, 1170, 1167, 1160, + /* 110 */ 1159, 1161, 1162, 1322, 1011, 1059, 1322, 1322, 1322, 1163, + /* 120 */ 1322, 1164, 1175, 1174, 1173, 1251, 1278, 1277, 1322, 1322, + /* 130 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 140 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 150 */ 1322, 1322, 1322, 1322, 1322, 1270, 1260, 1017, 1017, 1322, + /* 160 */ 1260, 1260, 1260, 1260, 1260, 1260, 1256, 1092, 1083, 1322, + /* 170 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 180 */ 1248, 1246, 1322, 1208, 1322, 1322, 1322, 1322, 1322, 1322, + /* 190 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 200 */ 1322, 1322, 1322, 1322, 1088, 1322, 1322, 1322, 1322, 1322, + /* 210 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1272, 1322, 1221, + /* 220 */ 1088, 1088, 1088, 1090, 1072, 1082, 997, 1127, 1106, 1106, + /* 230 */ 1311, 1127, 1311, 1034, 1292, 1031, 1117, 1106, 1190, 1117, + /* 240 */ 1117, 1089, 1082, 1322, 1314, 1097, 1097, 1313, 1313, 1097, + /* 250 */ 1138, 1062, 1127, 1068, 1068, 1068, 1068, 1097, 1008, 1127, + /* 260 */ 1138, 1062, 1062, 1127, 1097, 1008, 1225, 1308, 1097, 1097, + /* 270 */ 1008, 1201, 1097, 1008, 1097, 1008, 1201, 1060, 1060, 1060, + /* 280 */ 1049, 1201, 1060, 1034, 1060, 1049, 1060, 1060, 1110, 1105, + /* 290 */ 1110, 1105, 1110, 1105, 1110, 1105, 1097, 1196, 1097, 1322, + /* 300 */ 1201, 1205, 1205, 1201, 1122, 1111, 1120, 1118, 1127, 1014, + /* 310 */ 1052, 1275, 1275, 1271, 1271, 1271, 1319, 1319, 1256, 1287, + /* 320 */ 1287, 1036, 1036, 1287, 1322, 1322, 1322, 1322, 1322, 1322, + /* 330 */ 1282, 1322, 1210, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 340 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 350 */ 1322, 1143, 1322, 993, 1253, 1322, 1322, 1252, 1322, 1322, + /* 360 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 370 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1310, 1322, + /* 380 */ 1322, 1322, 1322, 1322, 1322, 1224, 1223, 1322, 1322, 1322, + /* 390 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 400 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, + /* 410 */ 1074, 1322, 1322, 1322, 1296, 1322, 1322, 1322, 1322, 1322, + /* 420 */ 1322, 1322, 1119, 1322, 1112, 1322, 1322, 1301, 1322, 1322, + /* 430 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1262, 1322, + /* 440 */ 1322, 1322, 1261, 1322, 1322, 1322, 1322, 1322, 1145, 1322, + /* 450 */ 1144, 1148, 1322, 1002, 1322, }; /********** End of lemon-generated parsing tables *****************************/ @@ -136294,73 +137785,87 @@ static const YYACTIONTYPE yy_default[] = { static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ 0, /* SEMI => nothing */ - 27, /* EXPLAIN => ID */ - 27, /* QUERY => ID */ - 27, /* PLAN => ID */ - 27, /* BEGIN => ID */ + 59, /* EXPLAIN => ID */ + 59, /* QUERY => ID */ + 59, /* PLAN => ID */ + 59, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ - 27, /* DEFERRED => ID */ - 27, /* IMMEDIATE => ID */ - 27, /* EXCLUSIVE => ID */ + 59, /* DEFERRED => ID */ + 59, /* IMMEDIATE => ID */ + 59, /* EXCLUSIVE => ID */ 0, /* COMMIT => nothing */ - 27, /* END => ID */ - 27, /* ROLLBACK => ID */ - 27, /* SAVEPOINT => ID */ - 27, /* RELEASE => ID */ + 59, /* END => ID */ + 59, /* ROLLBACK => ID */ + 59, /* SAVEPOINT => ID */ + 59, /* RELEASE => ID */ 0, /* TO => nothing */ 0, /* TABLE => nothing */ 0, /* CREATE => nothing */ - 27, /* IF => ID */ + 59, /* IF => ID */ 0, /* NOT => nothing */ 0, /* EXISTS => nothing */ - 27, /* TEMP => ID */ + 59, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ - 27, /* WITHOUT => ID */ + 59, /* WITHOUT => ID */ 0, /* COMMA => nothing */ + 59, /* ABORT => ID */ + 59, /* ACTION => ID */ + 59, /* AFTER => ID */ + 59, /* ANALYZE => ID */ + 59, /* ASC => ID */ + 59, /* ATTACH => ID */ + 59, /* BEFORE => ID */ + 59, /* BY => ID */ + 59, /* CASCADE => ID */ + 59, /* CAST => ID */ + 59, /* CONFLICT => ID */ + 59, /* DATABASE => ID */ + 59, /* DESC => ID */ + 59, /* DETACH => ID */ + 59, /* EACH => ID */ + 59, /* FAIL => ID */ + 0, /* OR => nothing */ + 0, /* AND => nothing */ + 0, /* IS => nothing */ + 59, /* MATCH => ID */ + 59, /* LIKE_KW => ID */ + 0, /* BETWEEN => nothing */ + 0, /* IN => nothing */ + 0, /* ISNULL => nothing */ + 0, /* NOTNULL => nothing */ + 0, /* NE => nothing */ + 0, /* EQ => nothing */ + 0, /* GT => nothing */ + 0, /* LE => nothing */ + 0, /* LT => nothing */ + 0, /* GE => nothing */ + 0, /* ESCAPE => nothing */ 0, /* ID => nothing */ - 27, /* ABORT => ID */ - 27, /* ACTION => ID */ - 27, /* AFTER => ID */ - 27, /* ANALYZE => ID */ - 27, /* ASC => ID */ - 27, /* ATTACH => ID */ - 27, /* BEFORE => ID */ - 27, /* BY => ID */ - 27, /* CASCADE => ID */ - 27, /* CAST => ID */ - 27, /* COLUMNKW => ID */ - 27, /* CONFLICT => ID */ - 27, /* DATABASE => ID */ - 27, /* DESC => ID */ - 27, /* DETACH => ID */ - 27, /* EACH => ID */ - 27, /* FAIL => ID */ - 27, /* FOR => ID */ - 27, /* IGNORE => ID */ - 27, /* INITIALLY => ID */ - 27, /* INSTEAD => ID */ - 27, /* LIKE_KW => ID */ - 27, /* MATCH => ID */ - 27, /* NO => ID */ - 27, /* KEY => ID */ - 27, /* OF => ID */ - 27, /* OFFSET => ID */ - 27, /* PRAGMA => ID */ - 27, /* RAISE => ID */ - 27, /* RECURSIVE => ID */ - 27, /* REPLACE => ID */ - 27, /* RESTRICT => ID */ - 27, /* ROW => ID */ - 27, /* TRIGGER => ID */ - 27, /* VACUUM => ID */ - 27, /* VIEW => ID */ - 27, /* VIRTUAL => ID */ - 27, /* WITH => ID */ - 27, /* REINDEX => ID */ - 27, /* RENAME => ID */ - 27, /* CTIME_KW => ID */ + 59, /* COLUMNKW => ID */ + 59, /* FOR => ID */ + 59, /* IGNORE => ID */ + 59, /* INITIALLY => ID */ + 59, /* INSTEAD => ID */ + 59, /* NO => ID */ + 59, /* KEY => ID */ + 59, /* OF => ID */ + 59, /* OFFSET => ID */ + 59, /* PRAGMA => ID */ + 59, /* RAISE => ID */ + 59, /* RECURSIVE => ID */ + 59, /* REPLACE => ID */ + 59, /* RESTRICT => ID */ + 59, /* ROW => ID */ + 59, /* TRIGGER => ID */ + 59, /* VACUUM => ID */ + 59, /* VIEW => ID */ + 59, /* VIRTUAL => ID */ + 59, /* WITH => ID */ + 59, /* REINDEX => ID */ + 59, /* RENAME => ID */ + 59, /* CTIME_KW => ID */ }; #endif /* YYFALLBACK */ @@ -136406,6 +137911,7 @@ struct yyParser { yyStackEntry yystk0; /* First stack entry */ #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ + yyStackEntry *yystackEnd; /* Last entry in the stack */ #endif }; typedef struct yyParser yyParser; @@ -136452,21 +137958,21 @@ static const char *const yyTokenName[] = { "ROLLBACK", "SAVEPOINT", "RELEASE", "TO", "TABLE", "CREATE", "IF", "NOT", "EXISTS", "TEMP", "LP", "RP", - "AS", "WITHOUT", "COMMA", "ID", - "ABORT", "ACTION", "AFTER", "ANALYZE", - "ASC", "ATTACH", "BEFORE", "BY", - "CASCADE", "CAST", "COLUMNKW", "CONFLICT", - "DATABASE", "DESC", "DETACH", "EACH", - "FAIL", "FOR", "IGNORE", "INITIALLY", - "INSTEAD", "LIKE_KW", "MATCH", "NO", - "KEY", "OF", "OFFSET", "PRAGMA", - "RAISE", "RECURSIVE", "REPLACE", "RESTRICT", - "ROW", "TRIGGER", "VACUUM", "VIEW", - "VIRTUAL", "WITH", "REINDEX", "RENAME", - "CTIME_KW", "ANY", "OR", "AND", - "IS", "BETWEEN", "IN", "ISNULL", - "NOTNULL", "NE", "EQ", "GT", - "LE", "LT", "GE", "ESCAPE", + "AS", "WITHOUT", "COMMA", "ABORT", + "ACTION", "AFTER", "ANALYZE", "ASC", + "ATTACH", "BEFORE", "BY", "CASCADE", + "CAST", "CONFLICT", "DATABASE", "DESC", + "DETACH", "EACH", "FAIL", "OR", + "AND", "IS", "MATCH", "LIKE_KW", + "BETWEEN", "IN", "ISNULL", "NOTNULL", + "NE", "EQ", "GT", "LE", + "LT", "GE", "ESCAPE", "ID", + "COLUMNKW", "FOR", "IGNORE", "INITIALLY", + "INSTEAD", "NO", "KEY", "OF", + "OFFSET", "PRAGMA", "RAISE", "RECURSIVE", + "REPLACE", "RESTRICT", "ROW", "TRIGGER", + "VACUUM", "VIEW", "VIRTUAL", "WITH", + "REINDEX", "RENAME", "CTIME_KW", "ANY", "BITAND", "BITOR", "LSHIFT", "RSHIFT", "PLUS", "MINUS", "STAR", "SLASH", "REM", "CONCAT", "COLLATE", "BITNOT", @@ -136524,330 +138030,327 @@ static const char *const yyRuleName[] = { /* 5 */ "transtype ::= DEFERRED", /* 6 */ "transtype ::= IMMEDIATE", /* 7 */ "transtype ::= EXCLUSIVE", - /* 8 */ "cmd ::= COMMIT trans_opt", - /* 9 */ "cmd ::= END trans_opt", - /* 10 */ "cmd ::= ROLLBACK trans_opt", - /* 11 */ "cmd ::= SAVEPOINT nm", - /* 12 */ "cmd ::= RELEASE savepoint_opt nm", - /* 13 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm", - /* 14 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm", - /* 15 */ "createkw ::= CREATE", - /* 16 */ "ifnotexists ::=", - /* 17 */ "ifnotexists ::= IF NOT EXISTS", - /* 18 */ "temp ::= TEMP", - /* 19 */ "temp ::=", - /* 20 */ "create_table_args ::= LP columnlist conslist_opt RP table_options", - /* 21 */ "create_table_args ::= AS select", - /* 22 */ "table_options ::=", - /* 23 */ "table_options ::= WITHOUT nm", - /* 24 */ "columnname ::= nm typetoken", - /* 25 */ "typetoken ::=", - /* 26 */ "typetoken ::= typename LP signed RP", - /* 27 */ "typetoken ::= typename LP signed COMMA signed RP", - /* 28 */ "typename ::= typename ID|STRING", - /* 29 */ "ccons ::= CONSTRAINT nm", - /* 30 */ "ccons ::= DEFAULT term", - /* 31 */ "ccons ::= DEFAULT LP expr RP", - /* 32 */ "ccons ::= DEFAULT PLUS term", - /* 33 */ "ccons ::= DEFAULT MINUS term", - /* 34 */ "ccons ::= DEFAULT ID|INDEXED", - /* 35 */ "ccons ::= NOT NULL onconf", - /* 36 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", - /* 37 */ "ccons ::= UNIQUE onconf", - /* 38 */ "ccons ::= CHECK LP expr RP", - /* 39 */ "ccons ::= REFERENCES nm eidlist_opt refargs", - /* 40 */ "ccons ::= defer_subclause", - /* 41 */ "ccons ::= COLLATE ID|STRING", - /* 42 */ "autoinc ::=", - /* 43 */ "autoinc ::= AUTOINCR", - /* 44 */ "refargs ::=", - /* 45 */ "refargs ::= refargs refarg", - /* 46 */ "refarg ::= MATCH nm", - /* 47 */ "refarg ::= ON INSERT refact", - /* 48 */ "refarg ::= ON DELETE refact", - /* 49 */ "refarg ::= ON UPDATE refact", - /* 50 */ "refact ::= SET NULL", - /* 51 */ "refact ::= SET DEFAULT", - /* 52 */ "refact ::= CASCADE", - /* 53 */ "refact ::= RESTRICT", - /* 54 */ "refact ::= NO ACTION", - /* 55 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", - /* 56 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", - /* 57 */ "init_deferred_pred_opt ::=", - /* 58 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", - /* 59 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", - /* 60 */ "conslist_opt ::=", - /* 61 */ "tconscomma ::= COMMA", - /* 62 */ "tcons ::= CONSTRAINT nm", - /* 63 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", - /* 64 */ "tcons ::= UNIQUE LP sortlist RP onconf", - /* 65 */ "tcons ::= CHECK LP expr RP onconf", - /* 66 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", - /* 67 */ "defer_subclause_opt ::=", - /* 68 */ "onconf ::=", - /* 69 */ "onconf ::= ON CONFLICT resolvetype", - /* 70 */ "orconf ::=", - /* 71 */ "orconf ::= OR resolvetype", - /* 72 */ "resolvetype ::= IGNORE", - /* 73 */ "resolvetype ::= REPLACE", - /* 74 */ "cmd ::= DROP TABLE ifexists fullname", - /* 75 */ "ifexists ::= IF EXISTS", - /* 76 */ "ifexists ::=", - /* 77 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", - /* 78 */ "cmd ::= DROP VIEW ifexists fullname", - /* 79 */ "cmd ::= select", - /* 80 */ "select ::= with selectnowith", - /* 81 */ "selectnowith ::= selectnowith multiselect_op oneselect", - /* 82 */ "multiselect_op ::= UNION", - /* 83 */ "multiselect_op ::= UNION ALL", - /* 84 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 85 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 86 */ "values ::= VALUES LP nexprlist RP", - /* 87 */ "values ::= values COMMA LP exprlist RP", - /* 88 */ "distinct ::= DISTINCT", - /* 89 */ "distinct ::= ALL", - /* 90 */ "distinct ::=", - /* 91 */ "sclp ::=", - /* 92 */ "selcollist ::= sclp expr as", - /* 93 */ "selcollist ::= sclp STAR", - /* 94 */ "selcollist ::= sclp nm DOT STAR", - /* 95 */ "as ::= AS nm", - /* 96 */ "as ::=", - /* 97 */ "from ::=", - /* 98 */ "from ::= FROM seltablist", - /* 99 */ "stl_prefix ::= seltablist joinop", - /* 100 */ "stl_prefix ::=", - /* 101 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 102 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", - /* 103 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 104 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 105 */ "dbnm ::=", - /* 106 */ "dbnm ::= DOT nm", - /* 107 */ "fullname ::= nm dbnm", - /* 108 */ "joinop ::= COMMA|JOIN", - /* 109 */ "joinop ::= JOIN_KW JOIN", - /* 110 */ "joinop ::= JOIN_KW nm JOIN", - /* 111 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 112 */ "on_opt ::= ON expr", - /* 113 */ "on_opt ::=", - /* 114 */ "indexed_opt ::=", - /* 115 */ "indexed_opt ::= INDEXED BY nm", - /* 116 */ "indexed_opt ::= NOT INDEXED", - /* 117 */ "using_opt ::= USING LP idlist RP", - /* 118 */ "using_opt ::=", - /* 119 */ "orderby_opt ::=", - /* 120 */ "orderby_opt ::= ORDER BY sortlist", - /* 121 */ "sortlist ::= sortlist COMMA expr sortorder", - /* 122 */ "sortlist ::= expr sortorder", - /* 123 */ "sortorder ::= ASC", - /* 124 */ "sortorder ::= DESC", - /* 125 */ "sortorder ::=", - /* 126 */ "groupby_opt ::=", - /* 127 */ "groupby_opt ::= GROUP BY nexprlist", - /* 128 */ "having_opt ::=", - /* 129 */ "having_opt ::= HAVING expr", - /* 130 */ "limit_opt ::=", - /* 131 */ "limit_opt ::= LIMIT expr", - /* 132 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 133 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 134 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", - /* 135 */ "where_opt ::=", - /* 136 */ "where_opt ::= WHERE expr", - /* 137 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", - /* 138 */ "setlist ::= setlist COMMA nm EQ expr", - /* 139 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 140 */ "setlist ::= nm EQ expr", - /* 141 */ "setlist ::= LP idlist RP EQ expr", - /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", - /* 143 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", - /* 144 */ "insert_cmd ::= INSERT orconf", - /* 145 */ "insert_cmd ::= REPLACE", - /* 146 */ "idlist_opt ::=", - /* 147 */ "idlist_opt ::= LP idlist RP", - /* 148 */ "idlist ::= idlist COMMA nm", - /* 149 */ "idlist ::= nm", - /* 150 */ "expr ::= LP expr RP", - /* 151 */ "term ::= NULL", - /* 152 */ "expr ::= ID|INDEXED", - /* 153 */ "expr ::= JOIN_KW", - /* 154 */ "expr ::= nm DOT nm", - /* 155 */ "expr ::= nm DOT nm DOT nm", - /* 156 */ "term ::= FLOAT|BLOB", - /* 157 */ "term ::= STRING", - /* 158 */ "term ::= INTEGER", - /* 159 */ "expr ::= VARIABLE", - /* 160 */ "expr ::= expr COLLATE ID|STRING", - /* 161 */ "expr ::= CAST LP expr AS typetoken RP", - /* 162 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 163 */ "expr ::= ID|INDEXED LP STAR RP", - /* 164 */ "term ::= CTIME_KW", - /* 165 */ "expr ::= LP nexprlist COMMA expr RP", - /* 166 */ "expr ::= expr AND expr", - /* 167 */ "expr ::= expr OR expr", - /* 168 */ "expr ::= expr LT|GT|GE|LE expr", - /* 169 */ "expr ::= expr EQ|NE expr", - /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 171 */ "expr ::= expr PLUS|MINUS expr", - /* 172 */ "expr ::= expr STAR|SLASH|REM expr", - /* 173 */ "expr ::= expr CONCAT expr", - /* 174 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 175 */ "expr ::= expr likeop expr", - /* 176 */ "expr ::= expr likeop expr ESCAPE expr", - /* 177 */ "expr ::= expr ISNULL|NOTNULL", - /* 178 */ "expr ::= expr NOT NULL", - /* 179 */ "expr ::= expr IS expr", - /* 180 */ "expr ::= expr IS NOT expr", - /* 181 */ "expr ::= NOT expr", - /* 182 */ "expr ::= BITNOT expr", - /* 183 */ "expr ::= MINUS expr", - /* 184 */ "expr ::= PLUS expr", - /* 185 */ "between_op ::= BETWEEN", - /* 186 */ "between_op ::= NOT BETWEEN", - /* 187 */ "expr ::= expr between_op expr AND expr", - /* 188 */ "in_op ::= IN", - /* 189 */ "in_op ::= NOT IN", - /* 190 */ "expr ::= expr in_op LP exprlist RP", - /* 191 */ "expr ::= LP select RP", - /* 192 */ "expr ::= expr in_op LP select RP", - /* 193 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 194 */ "expr ::= EXISTS LP select RP", - /* 195 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 196 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 197 */ "case_exprlist ::= WHEN expr THEN expr", - /* 198 */ "case_else ::= ELSE expr", - /* 199 */ "case_else ::=", - /* 200 */ "case_operand ::= expr", - /* 201 */ "case_operand ::=", - /* 202 */ "exprlist ::=", - /* 203 */ "nexprlist ::= nexprlist COMMA expr", - /* 204 */ "nexprlist ::= expr", - /* 205 */ "paren_exprlist ::=", - /* 206 */ "paren_exprlist ::= LP exprlist RP", - /* 207 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 208 */ "uniqueflag ::= UNIQUE", - /* 209 */ "uniqueflag ::=", - /* 210 */ "eidlist_opt ::=", - /* 211 */ "eidlist_opt ::= LP eidlist RP", - /* 212 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 213 */ "eidlist ::= nm collate sortorder", - /* 214 */ "collate ::=", - /* 215 */ "collate ::= COLLATE ID|STRING", - /* 216 */ "cmd ::= DROP INDEX ifexists fullname", - /* 217 */ "cmd ::= VACUUM", - /* 218 */ "cmd ::= VACUUM nm", - /* 219 */ "cmd ::= PRAGMA nm dbnm", - /* 220 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 221 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 222 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 223 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 224 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 225 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 226 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 227 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 228 */ "trigger_time ::= BEFORE", - /* 229 */ "trigger_time ::= AFTER", - /* 230 */ "trigger_time ::= INSTEAD OF", - /* 231 */ "trigger_time ::=", - /* 232 */ "trigger_event ::= DELETE|INSERT", - /* 233 */ "trigger_event ::= UPDATE", - /* 234 */ "trigger_event ::= UPDATE OF idlist", - /* 235 */ "when_clause ::=", - /* 236 */ "when_clause ::= WHEN expr", - /* 237 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 238 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 239 */ "trnm ::= nm DOT nm", - /* 240 */ "tridxby ::= INDEXED BY nm", - /* 241 */ "tridxby ::= NOT INDEXED", - /* 242 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 243 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", - /* 244 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 245 */ "trigger_cmd ::= select", - /* 246 */ "expr ::= RAISE LP IGNORE RP", - /* 247 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 248 */ "raisetype ::= ROLLBACK", - /* 249 */ "raisetype ::= ABORT", - /* 250 */ "raisetype ::= FAIL", - /* 251 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 252 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 253 */ "cmd ::= DETACH database_kw_opt expr", - /* 254 */ "key_opt ::=", - /* 255 */ "key_opt ::= KEY expr", - /* 256 */ "cmd ::= REINDEX", - /* 257 */ "cmd ::= REINDEX nm dbnm", - /* 258 */ "cmd ::= ANALYZE", - /* 259 */ "cmd ::= ANALYZE nm dbnm", - /* 260 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 261 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 262 */ "add_column_fullname ::= fullname", - /* 263 */ "cmd ::= create_vtab", - /* 264 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 265 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 266 */ "vtabarg ::=", - /* 267 */ "vtabargtoken ::= ANY", - /* 268 */ "vtabargtoken ::= lp anylist RP", - /* 269 */ "lp ::= LP", - /* 270 */ "with ::=", - /* 271 */ "with ::= WITH wqlist", - /* 272 */ "with ::= WITH RECURSIVE wqlist", - /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", - /* 275 */ "input ::= cmdlist", - /* 276 */ "cmdlist ::= cmdlist ecmd", - /* 277 */ "cmdlist ::= ecmd", - /* 278 */ "ecmd ::= SEMI", - /* 279 */ "ecmd ::= explain cmdx SEMI", - /* 280 */ "explain ::=", - /* 281 */ "trans_opt ::=", - /* 282 */ "trans_opt ::= TRANSACTION", - /* 283 */ "trans_opt ::= TRANSACTION nm", - /* 284 */ "savepoint_opt ::= SAVEPOINT", - /* 285 */ "savepoint_opt ::=", - /* 286 */ "cmd ::= create_table create_table_args", - /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 288 */ "columnlist ::= columnname carglist", - /* 289 */ "nm ::= ID|INDEXED", - /* 290 */ "nm ::= STRING", - /* 291 */ "nm ::= JOIN_KW", - /* 292 */ "typetoken ::= typename", - /* 293 */ "typename ::= ID|STRING", - /* 294 */ "signed ::= plus_num", - /* 295 */ "signed ::= minus_num", - /* 296 */ "carglist ::= carglist ccons", - /* 297 */ "carglist ::=", - /* 298 */ "ccons ::= NULL onconf", - /* 299 */ "conslist_opt ::= COMMA conslist", - /* 300 */ "conslist ::= conslist tconscomma tcons", - /* 301 */ "conslist ::= tcons", - /* 302 */ "tconscomma ::=", - /* 303 */ "defer_subclause_opt ::= defer_subclause", - /* 304 */ "resolvetype ::= raisetype", - /* 305 */ "selectnowith ::= oneselect", - /* 306 */ "oneselect ::= values", - /* 307 */ "sclp ::= selcollist COMMA", - /* 308 */ "as ::= ID|STRING", - /* 309 */ "expr ::= term", - /* 310 */ "likeop ::= LIKE_KW|MATCH", - /* 311 */ "exprlist ::= nexprlist", - /* 312 */ "nmnum ::= plus_num", - /* 313 */ "nmnum ::= nm", - /* 314 */ "nmnum ::= ON", - /* 315 */ "nmnum ::= DELETE", - /* 316 */ "nmnum ::= DEFAULT", - /* 317 */ "plus_num ::= INTEGER|FLOAT", - /* 318 */ "foreach_clause ::=", - /* 319 */ "foreach_clause ::= FOR EACH ROW", - /* 320 */ "trnm ::= nm", - /* 321 */ "tridxby ::=", - /* 322 */ "database_kw_opt ::= DATABASE", - /* 323 */ "database_kw_opt ::=", - /* 324 */ "kwcolumn_opt ::=", - /* 325 */ "kwcolumn_opt ::= COLUMNKW", - /* 326 */ "vtabarglist ::= vtabarg", - /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 328 */ "vtabarg ::= vtabarg vtabargtoken", - /* 329 */ "anylist ::=", - /* 330 */ "anylist ::= anylist LP anylist RP", - /* 331 */ "anylist ::= anylist ANY", + /* 8 */ "cmd ::= COMMIT|END trans_opt", + /* 9 */ "cmd ::= ROLLBACK trans_opt", + /* 10 */ "cmd ::= SAVEPOINT nm", + /* 11 */ "cmd ::= RELEASE savepoint_opt nm", + /* 12 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm", + /* 13 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm", + /* 14 */ "createkw ::= CREATE", + /* 15 */ "ifnotexists ::=", + /* 16 */ "ifnotexists ::= IF NOT EXISTS", + /* 17 */ "temp ::= TEMP", + /* 18 */ "temp ::=", + /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_options", + /* 20 */ "create_table_args ::= AS select", + /* 21 */ "table_options ::=", + /* 22 */ "table_options ::= WITHOUT nm", + /* 23 */ "columnname ::= nm typetoken", + /* 24 */ "typetoken ::=", + /* 25 */ "typetoken ::= typename LP signed RP", + /* 26 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 27 */ "typename ::= typename ID|STRING", + /* 28 */ "ccons ::= CONSTRAINT nm", + /* 29 */ "ccons ::= DEFAULT term", + /* 30 */ "ccons ::= DEFAULT LP expr RP", + /* 31 */ "ccons ::= DEFAULT PLUS term", + /* 32 */ "ccons ::= DEFAULT MINUS term", + /* 33 */ "ccons ::= DEFAULT ID|INDEXED", + /* 34 */ "ccons ::= NOT NULL onconf", + /* 35 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 36 */ "ccons ::= UNIQUE onconf", + /* 37 */ "ccons ::= CHECK LP expr RP", + /* 38 */ "ccons ::= REFERENCES nm eidlist_opt refargs", + /* 39 */ "ccons ::= defer_subclause", + /* 40 */ "ccons ::= COLLATE ID|STRING", + /* 41 */ "autoinc ::=", + /* 42 */ "autoinc ::= AUTOINCR", + /* 43 */ "refargs ::=", + /* 44 */ "refargs ::= refargs refarg", + /* 45 */ "refarg ::= MATCH nm", + /* 46 */ "refarg ::= ON INSERT refact", + /* 47 */ "refarg ::= ON DELETE refact", + /* 48 */ "refarg ::= ON UPDATE refact", + /* 49 */ "refact ::= SET NULL", + /* 50 */ "refact ::= SET DEFAULT", + /* 51 */ "refact ::= CASCADE", + /* 52 */ "refact ::= RESTRICT", + /* 53 */ "refact ::= NO ACTION", + /* 54 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 55 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 56 */ "init_deferred_pred_opt ::=", + /* 57 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 58 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 59 */ "conslist_opt ::=", + /* 60 */ "tconscomma ::= COMMA", + /* 61 */ "tcons ::= CONSTRAINT nm", + /* 62 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf", + /* 63 */ "tcons ::= UNIQUE LP sortlist RP onconf", + /* 64 */ "tcons ::= CHECK LP expr RP onconf", + /* 65 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt", + /* 66 */ "defer_subclause_opt ::=", + /* 67 */ "onconf ::=", + /* 68 */ "onconf ::= ON CONFLICT resolvetype", + /* 69 */ "orconf ::=", + /* 70 */ "orconf ::= OR resolvetype", + /* 71 */ "resolvetype ::= IGNORE", + /* 72 */ "resolvetype ::= REPLACE", + /* 73 */ "cmd ::= DROP TABLE ifexists fullname", + /* 74 */ "ifexists ::= IF EXISTS", + /* 75 */ "ifexists ::=", + /* 76 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", + /* 77 */ "cmd ::= DROP VIEW ifexists fullname", + /* 78 */ "cmd ::= select", + /* 79 */ "select ::= with selectnowith", + /* 80 */ "selectnowith ::= selectnowith multiselect_op oneselect", + /* 81 */ "multiselect_op ::= UNION", + /* 82 */ "multiselect_op ::= UNION ALL", + /* 83 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 84 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 85 */ "values ::= VALUES LP nexprlist RP", + /* 86 */ "values ::= values COMMA LP exprlist RP", + /* 87 */ "distinct ::= DISTINCT", + /* 88 */ "distinct ::= ALL", + /* 89 */ "distinct ::=", + /* 90 */ "sclp ::=", + /* 91 */ "selcollist ::= sclp expr as", + /* 92 */ "selcollist ::= sclp STAR", + /* 93 */ "selcollist ::= sclp nm DOT STAR", + /* 94 */ "as ::= AS nm", + /* 95 */ "as ::=", + /* 96 */ "from ::=", + /* 97 */ "from ::= FROM seltablist", + /* 98 */ "stl_prefix ::= seltablist joinop", + /* 99 */ "stl_prefix ::=", + /* 100 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", + /* 101 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", + /* 102 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", + /* 103 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", + /* 104 */ "dbnm ::=", + /* 105 */ "dbnm ::= DOT nm", + /* 106 */ "fullname ::= nm dbnm", + /* 107 */ "joinop ::= COMMA|JOIN", + /* 108 */ "joinop ::= JOIN_KW JOIN", + /* 109 */ "joinop ::= JOIN_KW nm JOIN", + /* 110 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 111 */ "on_opt ::= ON expr", + /* 112 */ "on_opt ::=", + /* 113 */ "indexed_opt ::=", + /* 114 */ "indexed_opt ::= INDEXED BY nm", + /* 115 */ "indexed_opt ::= NOT INDEXED", + /* 116 */ "using_opt ::= USING LP idlist RP", + /* 117 */ "using_opt ::=", + /* 118 */ "orderby_opt ::=", + /* 119 */ "orderby_opt ::= ORDER BY sortlist", + /* 120 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 121 */ "sortlist ::= expr sortorder", + /* 122 */ "sortorder ::= ASC", + /* 123 */ "sortorder ::= DESC", + /* 124 */ "sortorder ::=", + /* 125 */ "groupby_opt ::=", + /* 126 */ "groupby_opt ::= GROUP BY nexprlist", + /* 127 */ "having_opt ::=", + /* 128 */ "having_opt ::= HAVING expr", + /* 129 */ "limit_opt ::=", + /* 130 */ "limit_opt ::= LIMIT expr", + /* 131 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 132 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 133 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", + /* 134 */ "where_opt ::=", + /* 135 */ "where_opt ::= WHERE expr", + /* 136 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", + /* 137 */ "setlist ::= setlist COMMA nm EQ expr", + /* 138 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 139 */ "setlist ::= nm EQ expr", + /* 140 */ "setlist ::= LP idlist RP EQ expr", + /* 141 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", + /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", + /* 143 */ "insert_cmd ::= INSERT orconf", + /* 144 */ "insert_cmd ::= REPLACE", + /* 145 */ "idlist_opt ::=", + /* 146 */ "idlist_opt ::= LP idlist RP", + /* 147 */ "idlist ::= idlist COMMA nm", + /* 148 */ "idlist ::= nm", + /* 149 */ "expr ::= LP expr RP", + /* 150 */ "expr ::= ID|INDEXED", + /* 151 */ "expr ::= JOIN_KW", + /* 152 */ "expr ::= nm DOT nm", + /* 153 */ "expr ::= nm DOT nm DOT nm", + /* 154 */ "term ::= NULL|FLOAT|BLOB", + /* 155 */ "term ::= STRING", + /* 156 */ "term ::= INTEGER", + /* 157 */ "expr ::= VARIABLE", + /* 158 */ "expr ::= expr COLLATE ID|STRING", + /* 159 */ "expr ::= CAST LP expr AS typetoken RP", + /* 160 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 161 */ "expr ::= ID|INDEXED LP STAR RP", + /* 162 */ "term ::= CTIME_KW", + /* 163 */ "expr ::= LP nexprlist COMMA expr RP", + /* 164 */ "expr ::= expr AND expr", + /* 165 */ "expr ::= expr OR expr", + /* 166 */ "expr ::= expr LT|GT|GE|LE expr", + /* 167 */ "expr ::= expr EQ|NE expr", + /* 168 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 169 */ "expr ::= expr PLUS|MINUS expr", + /* 170 */ "expr ::= expr STAR|SLASH|REM expr", + /* 171 */ "expr ::= expr CONCAT expr", + /* 172 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 173 */ "expr ::= expr likeop expr", + /* 174 */ "expr ::= expr likeop expr ESCAPE expr", + /* 175 */ "expr ::= expr ISNULL|NOTNULL", + /* 176 */ "expr ::= expr NOT NULL", + /* 177 */ "expr ::= expr IS expr", + /* 178 */ "expr ::= expr IS NOT expr", + /* 179 */ "expr ::= NOT expr", + /* 180 */ "expr ::= BITNOT expr", + /* 181 */ "expr ::= MINUS expr", + /* 182 */ "expr ::= PLUS expr", + /* 183 */ "between_op ::= BETWEEN", + /* 184 */ "between_op ::= NOT BETWEEN", + /* 185 */ "expr ::= expr between_op expr AND expr", + /* 186 */ "in_op ::= IN", + /* 187 */ "in_op ::= NOT IN", + /* 188 */ "expr ::= expr in_op LP exprlist RP", + /* 189 */ "expr ::= LP select RP", + /* 190 */ "expr ::= expr in_op LP select RP", + /* 191 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 192 */ "expr ::= EXISTS LP select RP", + /* 193 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 194 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 195 */ "case_exprlist ::= WHEN expr THEN expr", + /* 196 */ "case_else ::= ELSE expr", + /* 197 */ "case_else ::=", + /* 198 */ "case_operand ::= expr", + /* 199 */ "case_operand ::=", + /* 200 */ "exprlist ::=", + /* 201 */ "nexprlist ::= nexprlist COMMA expr", + /* 202 */ "nexprlist ::= expr", + /* 203 */ "paren_exprlist ::=", + /* 204 */ "paren_exprlist ::= LP exprlist RP", + /* 205 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 206 */ "uniqueflag ::= UNIQUE", + /* 207 */ "uniqueflag ::=", + /* 208 */ "eidlist_opt ::=", + /* 209 */ "eidlist_opt ::= LP eidlist RP", + /* 210 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 211 */ "eidlist ::= nm collate sortorder", + /* 212 */ "collate ::=", + /* 213 */ "collate ::= COLLATE ID|STRING", + /* 214 */ "cmd ::= DROP INDEX ifexists fullname", + /* 215 */ "cmd ::= VACUUM", + /* 216 */ "cmd ::= VACUUM nm", + /* 217 */ "cmd ::= PRAGMA nm dbnm", + /* 218 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 219 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 220 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 221 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 222 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 223 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 224 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 225 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 226 */ "trigger_time ::= BEFORE|AFTER", + /* 227 */ "trigger_time ::= INSTEAD OF", + /* 228 */ "trigger_time ::=", + /* 229 */ "trigger_event ::= DELETE|INSERT", + /* 230 */ "trigger_event ::= UPDATE", + /* 231 */ "trigger_event ::= UPDATE OF idlist", + /* 232 */ "when_clause ::=", + /* 233 */ "when_clause ::= WHEN expr", + /* 234 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 235 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 236 */ "trnm ::= nm DOT nm", + /* 237 */ "tridxby ::= INDEXED BY nm", + /* 238 */ "tridxby ::= NOT INDEXED", + /* 239 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 240 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", + /* 241 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 242 */ "trigger_cmd ::= select", + /* 243 */ "expr ::= RAISE LP IGNORE RP", + /* 244 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 245 */ "raisetype ::= ROLLBACK", + /* 246 */ "raisetype ::= ABORT", + /* 247 */ "raisetype ::= FAIL", + /* 248 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 249 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 250 */ "cmd ::= DETACH database_kw_opt expr", + /* 251 */ "key_opt ::=", + /* 252 */ "key_opt ::= KEY expr", + /* 253 */ "cmd ::= REINDEX", + /* 254 */ "cmd ::= REINDEX nm dbnm", + /* 255 */ "cmd ::= ANALYZE", + /* 256 */ "cmd ::= ANALYZE nm dbnm", + /* 257 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 258 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 259 */ "add_column_fullname ::= fullname", + /* 260 */ "cmd ::= create_vtab", + /* 261 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 262 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 263 */ "vtabarg ::=", + /* 264 */ "vtabargtoken ::= ANY", + /* 265 */ "vtabargtoken ::= lp anylist RP", + /* 266 */ "lp ::= LP", + /* 267 */ "with ::=", + /* 268 */ "with ::= WITH wqlist", + /* 269 */ "with ::= WITH RECURSIVE wqlist", + /* 270 */ "wqlist ::= nm eidlist_opt AS LP select RP", + /* 271 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 272 */ "input ::= cmdlist", + /* 273 */ "cmdlist ::= cmdlist ecmd", + /* 274 */ "cmdlist ::= ecmd", + /* 275 */ "ecmd ::= SEMI", + /* 276 */ "ecmd ::= explain cmdx SEMI", + /* 277 */ "explain ::=", + /* 278 */ "trans_opt ::=", + /* 279 */ "trans_opt ::= TRANSACTION", + /* 280 */ "trans_opt ::= TRANSACTION nm", + /* 281 */ "savepoint_opt ::= SAVEPOINT", + /* 282 */ "savepoint_opt ::=", + /* 283 */ "cmd ::= create_table create_table_args", + /* 284 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 285 */ "columnlist ::= columnname carglist", + /* 286 */ "nm ::= ID|INDEXED", + /* 287 */ "nm ::= STRING", + /* 288 */ "nm ::= JOIN_KW", + /* 289 */ "typetoken ::= typename", + /* 290 */ "typename ::= ID|STRING", + /* 291 */ "signed ::= plus_num", + /* 292 */ "signed ::= minus_num", + /* 293 */ "carglist ::= carglist ccons", + /* 294 */ "carglist ::=", + /* 295 */ "ccons ::= NULL onconf", + /* 296 */ "conslist_opt ::= COMMA conslist", + /* 297 */ "conslist ::= conslist tconscomma tcons", + /* 298 */ "conslist ::= tcons", + /* 299 */ "tconscomma ::=", + /* 300 */ "defer_subclause_opt ::= defer_subclause", + /* 301 */ "resolvetype ::= raisetype", + /* 302 */ "selectnowith ::= oneselect", + /* 303 */ "oneselect ::= values", + /* 304 */ "sclp ::= selcollist COMMA", + /* 305 */ "as ::= ID|STRING", + /* 306 */ "expr ::= term", + /* 307 */ "likeop ::= LIKE_KW|MATCH", + /* 308 */ "exprlist ::= nexprlist", + /* 309 */ "nmnum ::= plus_num", + /* 310 */ "nmnum ::= nm", + /* 311 */ "nmnum ::= ON", + /* 312 */ "nmnum ::= DELETE", + /* 313 */ "nmnum ::= DEFAULT", + /* 314 */ "plus_num ::= INTEGER|FLOAT", + /* 315 */ "foreach_clause ::=", + /* 316 */ "foreach_clause ::= FOR EACH ROW", + /* 317 */ "trnm ::= nm", + /* 318 */ "tridxby ::=", + /* 319 */ "database_kw_opt ::= DATABASE", + /* 320 */ "database_kw_opt ::=", + /* 321 */ "kwcolumn_opt ::=", + /* 322 */ "kwcolumn_opt ::= COLUMNKW", + /* 323 */ "vtabarglist ::= vtabarg", + /* 324 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 325 */ "vtabarg ::= vtabarg vtabargtoken", + /* 326 */ "anylist ::=", + /* 327 */ "anylist ::= anylist LP anylist RP", + /* 328 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ @@ -136916,6 +138419,9 @@ SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ pParser->yytos = pParser->yystack; pParser->yystack[0].stateno = 0; pParser->yystack[0].major = 0; +#if YYSTACKDEPTH>0 + pParser->yystackEnd = &pParser->yystack[YYSTACKDEPTH-1]; +#endif } #ifndef sqlite3Parser_ENGINEALWAYSONSTACK @@ -137258,7 +138764,7 @@ static void yy_shift( } #endif #if YYSTACKDEPTH>0 - if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){ + if( yypParser->yytos>yypParser->yystackEnd ){ yypParser->yytos--; yyStackOverflow(yypParser); return; @@ -137286,341 +138792,338 @@ static void yy_shift( ** is used during the reduce. */ static const struct { - YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - unsigned char nrhs; /* Number of right-hand side symbols in the rule */ + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ } yyRuleInfo[] = { - { 147, 1 }, - { 147, 3 }, - { 148, 1 }, - { 149, 3 }, + { 147, -1 }, + { 147, -3 }, + { 148, -1 }, + { 149, -3 }, { 150, 0 }, - { 150, 1 }, - { 150, 1 }, - { 150, 1 }, - { 149, 2 }, - { 149, 2 }, - { 149, 2 }, - { 149, 2 }, - { 149, 3 }, - { 149, 5 }, - { 154, 6 }, - { 156, 1 }, + { 150, -1 }, + { 150, -1 }, + { 150, -1 }, + { 149, -2 }, + { 149, -2 }, + { 149, -2 }, + { 149, -3 }, + { 149, -5 }, + { 154, -6 }, + { 156, -1 }, { 158, 0 }, - { 158, 3 }, - { 157, 1 }, + { 158, -3 }, + { 157, -1 }, { 157, 0 }, - { 155, 5 }, - { 155, 2 }, + { 155, -5 }, + { 155, -2 }, { 162, 0 }, - { 162, 2 }, - { 164, 2 }, + { 162, -2 }, + { 164, -2 }, { 166, 0 }, - { 166, 4 }, - { 166, 6 }, - { 167, 2 }, - { 171, 2 }, - { 171, 2 }, - { 171, 4 }, - { 171, 3 }, - { 171, 3 }, - { 171, 2 }, - { 171, 3 }, - { 171, 5 }, - { 171, 2 }, - { 171, 4 }, - { 171, 4 }, - { 171, 1 }, - { 171, 2 }, + { 166, -4 }, + { 166, -6 }, + { 167, -2 }, + { 171, -2 }, + { 171, -2 }, + { 171, -4 }, + { 171, -3 }, + { 171, -3 }, + { 171, -2 }, + { 171, -3 }, + { 171, -5 }, + { 171, -2 }, + { 171, -4 }, + { 171, -4 }, + { 171, -1 }, + { 171, -2 }, { 176, 0 }, - { 176, 1 }, + { 176, -1 }, { 178, 0 }, - { 178, 2 }, - { 180, 2 }, - { 180, 3 }, - { 180, 3 }, - { 180, 3 }, - { 181, 2 }, - { 181, 2 }, - { 181, 1 }, - { 181, 1 }, - { 181, 2 }, - { 179, 3 }, - { 179, 2 }, + { 178, -2 }, + { 180, -2 }, + { 180, -3 }, + { 180, -3 }, + { 180, -3 }, + { 181, -2 }, + { 181, -2 }, + { 181, -1 }, + { 181, -1 }, + { 181, -2 }, + { 179, -3 }, + { 179, -2 }, { 182, 0 }, - { 182, 2 }, - { 182, 2 }, + { 182, -2 }, + { 182, -2 }, { 161, 0 }, - { 184, 1 }, - { 185, 2 }, - { 185, 7 }, - { 185, 5 }, - { 185, 5 }, - { 185, 10 }, + { 184, -1 }, + { 185, -2 }, + { 185, -7 }, + { 185, -5 }, + { 185, -5 }, + { 185, -10 }, { 188, 0 }, { 174, 0 }, - { 174, 3 }, + { 174, -3 }, { 189, 0 }, - { 189, 2 }, - { 190, 1 }, - { 190, 1 }, - { 149, 4 }, - { 192, 2 }, + { 189, -2 }, + { 190, -1 }, + { 190, -1 }, + { 149, -4 }, + { 192, -2 }, { 192, 0 }, - { 149, 9 }, - { 149, 4 }, - { 149, 1 }, - { 163, 2 }, - { 194, 3 }, - { 197, 1 }, - { 197, 2 }, - { 197, 1 }, - { 195, 9 }, - { 206, 4 }, - { 206, 5 }, - { 198, 1 }, - { 198, 1 }, + { 149, -9 }, + { 149, -4 }, + { 149, -1 }, + { 163, -2 }, + { 194, -3 }, + { 197, -1 }, + { 197, -2 }, + { 197, -1 }, + { 195, -9 }, + { 206, -4 }, + { 206, -5 }, + { 198, -1 }, + { 198, -1 }, { 198, 0 }, { 209, 0 }, - { 199, 3 }, - { 199, 2 }, - { 199, 4 }, - { 210, 2 }, + { 199, -3 }, + { 199, -2 }, + { 199, -4 }, + { 210, -2 }, { 210, 0 }, { 200, 0 }, - { 200, 2 }, - { 212, 2 }, + { 200, -2 }, + { 212, -2 }, { 212, 0 }, - { 211, 7 }, - { 211, 9 }, - { 211, 7 }, - { 211, 7 }, + { 211, -7 }, + { 211, -9 }, + { 211, -7 }, + { 211, -7 }, { 159, 0 }, - { 159, 2 }, - { 193, 2 }, - { 213, 1 }, - { 213, 2 }, - { 213, 3 }, - { 213, 4 }, - { 215, 2 }, + { 159, -2 }, + { 193, -2 }, + { 213, -1 }, + { 213, -2 }, + { 213, -3 }, + { 213, -4 }, + { 215, -2 }, { 215, 0 }, { 214, 0 }, - { 214, 3 }, - { 214, 2 }, - { 216, 4 }, + { 214, -3 }, + { 214, -2 }, + { 216, -4 }, { 216, 0 }, { 204, 0 }, - { 204, 3 }, - { 186, 4 }, - { 186, 2 }, - { 175, 1 }, - { 175, 1 }, + { 204, -3 }, + { 186, -4 }, + { 186, -2 }, + { 175, -1 }, + { 175, -1 }, { 175, 0 }, { 202, 0 }, - { 202, 3 }, + { 202, -3 }, { 203, 0 }, - { 203, 2 }, + { 203, -2 }, { 205, 0 }, - { 205, 2 }, - { 205, 4 }, - { 205, 4 }, - { 149, 6 }, + { 205, -2 }, + { 205, -4 }, + { 205, -4 }, + { 149, -6 }, { 201, 0 }, - { 201, 2 }, - { 149, 8 }, - { 218, 5 }, - { 218, 7 }, - { 218, 3 }, - { 218, 5 }, - { 149, 6 }, - { 149, 7 }, - { 219, 2 }, - { 219, 1 }, + { 201, -2 }, + { 149, -8 }, + { 218, -5 }, + { 218, -7 }, + { 218, -3 }, + { 218, -5 }, + { 149, -6 }, + { 149, -7 }, + { 219, -2 }, + { 219, -1 }, { 220, 0 }, - { 220, 3 }, - { 217, 3 }, - { 217, 1 }, - { 173, 3 }, - { 172, 1 }, - { 173, 1 }, - { 173, 1 }, - { 173, 3 }, - { 173, 5 }, - { 172, 1 }, - { 172, 1 }, - { 172, 1 }, - { 173, 1 }, - { 173, 3 }, - { 173, 6 }, - { 173, 5 }, - { 173, 4 }, - { 172, 1 }, - { 173, 5 }, - { 173, 3 }, - { 173, 3 }, - { 173, 3 }, - { 173, 3 }, - { 173, 3 }, - { 173, 3 }, - { 173, 3 }, - { 173, 3 }, - { 221, 2 }, - { 173, 3 }, - { 173, 5 }, - { 173, 2 }, - { 173, 3 }, - { 173, 3 }, - { 173, 4 }, - { 173, 2 }, - { 173, 2 }, - { 173, 2 }, - { 173, 2 }, - { 222, 1 }, - { 222, 2 }, - { 173, 5 }, - { 223, 1 }, - { 223, 2 }, - { 173, 5 }, - { 173, 3 }, - { 173, 5 }, - { 173, 5 }, - { 173, 4 }, - { 173, 5 }, - { 226, 5 }, - { 226, 4 }, - { 227, 2 }, + { 220, -3 }, + { 217, -3 }, + { 217, -1 }, + { 173, -3 }, + { 173, -1 }, + { 173, -1 }, + { 173, -3 }, + { 173, -5 }, + { 172, -1 }, + { 172, -1 }, + { 172, -1 }, + { 173, -1 }, + { 173, -3 }, + { 173, -6 }, + { 173, -5 }, + { 173, -4 }, + { 172, -1 }, + { 173, -5 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 173, -3 }, + { 221, -2 }, + { 173, -3 }, + { 173, -5 }, + { 173, -2 }, + { 173, -3 }, + { 173, -3 }, + { 173, -4 }, + { 173, -2 }, + { 173, -2 }, + { 173, -2 }, + { 173, -2 }, + { 222, -1 }, + { 222, -2 }, + { 173, -5 }, + { 223, -1 }, + { 223, -2 }, + { 173, -5 }, + { 173, -3 }, + { 173, -5 }, + { 173, -5 }, + { 173, -4 }, + { 173, -5 }, + { 226, -5 }, + { 226, -4 }, + { 227, -2 }, { 227, 0 }, - { 225, 1 }, + { 225, -1 }, { 225, 0 }, { 208, 0 }, - { 207, 3 }, - { 207, 1 }, + { 207, -3 }, + { 207, -1 }, { 224, 0 }, - { 224, 3 }, - { 149, 12 }, - { 228, 1 }, + { 224, -3 }, + { 149, -12 }, + { 228, -1 }, { 228, 0 }, { 177, 0 }, - { 177, 3 }, - { 187, 5 }, - { 187, 3 }, + { 177, -3 }, + { 187, -5 }, + { 187, -3 }, { 229, 0 }, - { 229, 2 }, - { 149, 4 }, - { 149, 1 }, - { 149, 2 }, - { 149, 3 }, - { 149, 5 }, - { 149, 6 }, - { 149, 5 }, - { 149, 6 }, - { 169, 2 }, - { 170, 2 }, - { 149, 5 }, - { 231, 11 }, - { 233, 1 }, - { 233, 1 }, - { 233, 2 }, + { 229, -2 }, + { 149, -4 }, + { 149, -1 }, + { 149, -2 }, + { 149, -3 }, + { 149, -5 }, + { 149, -6 }, + { 149, -5 }, + { 149, -6 }, + { 169, -2 }, + { 170, -2 }, + { 149, -5 }, + { 231, -11 }, + { 233, -1 }, + { 233, -2 }, { 233, 0 }, - { 234, 1 }, - { 234, 1 }, - { 234, 3 }, + { 234, -1 }, + { 234, -1 }, + { 234, -3 }, { 236, 0 }, - { 236, 2 }, - { 232, 3 }, - { 232, 2 }, - { 238, 3 }, - { 239, 3 }, - { 239, 2 }, - { 237, 7 }, - { 237, 5 }, - { 237, 5 }, - { 237, 1 }, - { 173, 4 }, - { 173, 6 }, - { 191, 1 }, - { 191, 1 }, - { 191, 1 }, - { 149, 4 }, - { 149, 6 }, - { 149, 3 }, + { 236, -2 }, + { 232, -3 }, + { 232, -2 }, + { 238, -3 }, + { 239, -3 }, + { 239, -2 }, + { 237, -7 }, + { 237, -5 }, + { 237, -5 }, + { 237, -1 }, + { 173, -4 }, + { 173, -6 }, + { 191, -1 }, + { 191, -1 }, + { 191, -1 }, + { 149, -4 }, + { 149, -6 }, + { 149, -3 }, { 241, 0 }, - { 241, 2 }, - { 149, 1 }, - { 149, 3 }, - { 149, 1 }, - { 149, 3 }, - { 149, 6 }, - { 149, 7 }, - { 242, 1 }, - { 149, 1 }, - { 149, 4 }, - { 244, 8 }, + { 241, -2 }, + { 149, -1 }, + { 149, -3 }, + { 149, -1 }, + { 149, -3 }, + { 149, -6 }, + { 149, -7 }, + { 242, -1 }, + { 149, -1 }, + { 149, -4 }, + { 244, -8 }, { 246, 0 }, - { 247, 1 }, - { 247, 3 }, - { 248, 1 }, + { 247, -1 }, + { 247, -3 }, + { 248, -1 }, { 196, 0 }, - { 196, 2 }, - { 196, 3 }, - { 250, 6 }, - { 250, 8 }, - { 144, 1 }, - { 145, 2 }, - { 145, 1 }, - { 146, 1 }, - { 146, 3 }, + { 196, -2 }, + { 196, -3 }, + { 250, -6 }, + { 250, -8 }, + { 144, -1 }, + { 145, -2 }, + { 145, -1 }, + { 146, -1 }, + { 146, -3 }, { 147, 0 }, { 151, 0 }, - { 151, 1 }, - { 151, 2 }, - { 153, 1 }, + { 151, -1 }, + { 151, -2 }, + { 153, -1 }, { 153, 0 }, - { 149, 2 }, - { 160, 4 }, - { 160, 2 }, - { 152, 1 }, - { 152, 1 }, - { 152, 1 }, - { 166, 1 }, - { 167, 1 }, - { 168, 1 }, - { 168, 1 }, - { 165, 2 }, + { 149, -2 }, + { 160, -4 }, + { 160, -2 }, + { 152, -1 }, + { 152, -1 }, + { 152, -1 }, + { 166, -1 }, + { 167, -1 }, + { 168, -1 }, + { 168, -1 }, + { 165, -2 }, { 165, 0 }, - { 171, 2 }, - { 161, 2 }, - { 183, 3 }, - { 183, 1 }, + { 171, -2 }, + { 161, -2 }, + { 183, -3 }, + { 183, -1 }, { 184, 0 }, - { 188, 1 }, - { 190, 1 }, - { 194, 1 }, - { 195, 1 }, - { 209, 2 }, - { 210, 1 }, - { 173, 1 }, - { 221, 1 }, - { 208, 1 }, - { 230, 1 }, - { 230, 1 }, - { 230, 1 }, - { 230, 1 }, - { 230, 1 }, - { 169, 1 }, + { 188, -1 }, + { 190, -1 }, + { 194, -1 }, + { 195, -1 }, + { 209, -2 }, + { 210, -1 }, + { 173, -1 }, + { 221, -1 }, + { 208, -1 }, + { 230, -1 }, + { 230, -1 }, + { 230, -1 }, + { 230, -1 }, + { 230, -1 }, + { 169, -1 }, { 235, 0 }, - { 235, 3 }, - { 238, 1 }, + { 235, -3 }, + { 238, -1 }, { 239, 0 }, - { 240, 1 }, + { 240, -1 }, { 240, 0 }, { 243, 0 }, - { 243, 1 }, - { 245, 1 }, - { 245, 3 }, - { 246, 2 }, + { 243, -1 }, + { 245, -1 }, + { 245, -3 }, + { 246, -2 }, { 249, 0 }, - { 249, 4 }, - { 249, 2 }, + { 249, -4 }, + { 249, -2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -137643,7 +139146,7 @@ static void yy_reduce( if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[-yysize].stateno); + yyRuleName[yyruleno], yymsp[yysize].stateno); } #endif /* NDEBUG */ @@ -137658,7 +139161,7 @@ static void yy_reduce( } #endif #if YYSTACKDEPTH>0 - if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){ + if( yypParser->yytos>=yypParser->yystackEnd ){ yyStackOverflow(yypParser); return; } @@ -137704,66 +139207,63 @@ static void yy_reduce( case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); {yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/} break; - case 8: /* cmd ::= COMMIT trans_opt */ - case 9: /* cmd ::= END trans_opt */ yytestcase(yyruleno==9); -{sqlite3CommitTransaction(pParse);} - break; - case 10: /* cmd ::= ROLLBACK trans_opt */ -{sqlite3RollbackTransaction(pParse);} + case 8: /* cmd ::= COMMIT|END trans_opt */ + case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); +{sqlite3EndTransaction(pParse,yymsp[-1].major);} break; - case 11: /* cmd ::= SAVEPOINT nm */ + case 10: /* cmd ::= SAVEPOINT nm */ { sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0); } break; - case 12: /* cmd ::= RELEASE savepoint_opt nm */ + case 11: /* cmd ::= RELEASE savepoint_opt nm */ { sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0); } break; - case 13: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ { sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0); } break; - case 14: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194); } break; - case 15: /* createkw ::= CREATE */ + case 14: /* createkw ::= CREATE */ {disableLookaside(pParse);} break; - case 16: /* ifnotexists ::= */ - case 19: /* temp ::= */ yytestcase(yyruleno==19); - case 22: /* table_options ::= */ yytestcase(yyruleno==22); - case 42: /* autoinc ::= */ yytestcase(yyruleno==42); - case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); - case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); - case 76: /* ifexists ::= */ yytestcase(yyruleno==76); - case 90: /* distinct ::= */ yytestcase(yyruleno==90); - case 214: /* collate ::= */ yytestcase(yyruleno==214); + case 15: /* ifnotexists ::= */ + case 18: /* temp ::= */ yytestcase(yyruleno==18); + case 21: /* table_options ::= */ yytestcase(yyruleno==21); + case 41: /* autoinc ::= */ yytestcase(yyruleno==41); + case 56: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==56); + case 66: /* defer_subclause_opt ::= */ yytestcase(yyruleno==66); + case 75: /* ifexists ::= */ yytestcase(yyruleno==75); + case 89: /* distinct ::= */ yytestcase(yyruleno==89); + case 212: /* collate ::= */ yytestcase(yyruleno==212); {yymsp[1].minor.yy194 = 0;} break; - case 17: /* ifnotexists ::= IF NOT EXISTS */ + case 16: /* ifnotexists ::= IF NOT EXISTS */ {yymsp[-2].minor.yy194 = 1;} break; - case 18: /* temp ::= TEMP */ - case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43); + case 17: /* temp ::= TEMP */ + case 42: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==42); {yymsp[0].minor.yy194 = 1;} break; - case 20: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ + case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ { sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy194,0); } break; - case 21: /* create_table_args ::= AS select */ + case 20: /* create_table_args ::= AS select */ { sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy243); sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); } break; - case 23: /* table_options ::= WITHOUT nm */ + case 22: /* table_options ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ yymsp[-1].minor.yy194 = TF_WithoutRowid | TF_NoVisibleRowid; @@ -137773,39 +139273,39 @@ static void yy_reduce( } } break; - case 24: /* columnname ::= nm typetoken */ + case 23: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; - case 25: /* typetoken ::= */ - case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60); - case 96: /* as ::= */ yytestcase(yyruleno==96); + case 24: /* typetoken ::= */ + case 59: /* conslist_opt ::= */ yytestcase(yyruleno==59); + case 95: /* as ::= */ yytestcase(yyruleno==95); {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} break; - case 26: /* typetoken ::= typename LP signed RP */ + case 25: /* typetoken ::= typename LP signed RP */ { yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z); } break; - case 27: /* typetoken ::= typename LP signed COMMA signed RP */ + case 26: /* typetoken ::= typename LP signed COMMA signed RP */ { yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z); } break; - case 28: /* typename ::= typename ID|STRING */ + case 27: /* typename ::= typename ID|STRING */ {yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);} break; - case 29: /* ccons ::= CONSTRAINT nm */ - case 62: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==62); + case 28: /* ccons ::= CONSTRAINT nm */ + case 61: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==61); {pParse->constraintName = yymsp[0].minor.yy0;} break; - case 30: /* ccons ::= DEFAULT term */ - case 32: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==32); + case 29: /* ccons ::= DEFAULT term */ + case 31: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==31); {sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);} break; - case 31: /* ccons ::= DEFAULT LP expr RP */ + case 30: /* ccons ::= DEFAULT LP expr RP */ {sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);} break; - case 33: /* ccons ::= DEFAULT MINUS term */ + case 32: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0); @@ -137814,142 +139314,142 @@ static void yy_reduce( sqlite3AddDefaultValue(pParse,&v); } break; - case 34: /* ccons ::= DEFAULT ID|INDEXED */ + case 33: /* ccons ::= DEFAULT ID|INDEXED */ { ExprSpan v; spanExpr(&v, pParse, TK_STRING, yymsp[0].minor.yy0); sqlite3AddDefaultValue(pParse,&v); } break; - case 35: /* ccons ::= NOT NULL onconf */ + case 34: /* ccons ::= NOT NULL onconf */ {sqlite3AddNotNull(pParse, yymsp[0].minor.yy194);} break; - case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ + case 35: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ {sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);} break; - case 37: /* ccons ::= UNIQUE onconf */ + case 36: /* ccons ::= UNIQUE onconf */ {sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy194,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 38: /* ccons ::= CHECK LP expr RP */ + case 37: /* ccons ::= CHECK LP expr RP */ {sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);} break; - case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */ + case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */ {sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);} break; - case 40: /* ccons ::= defer_subclause */ + case 39: /* ccons ::= defer_subclause */ {sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy194);} break; - case 41: /* ccons ::= COLLATE ID|STRING */ + case 40: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; - case 44: /* refargs ::= */ + case 43: /* refargs ::= */ { yymsp[1].minor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */} break; - case 45: /* refargs ::= refargs refarg */ + case 44: /* refargs ::= refargs refarg */ { yymsp[-1].minor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; } break; - case 46: /* refarg ::= MATCH nm */ + case 45: /* refarg ::= MATCH nm */ { yymsp[-1].minor.yy497.value = 0; yymsp[-1].minor.yy497.mask = 0x000000; } break; - case 47: /* refarg ::= ON INSERT refact */ + case 46: /* refarg ::= ON INSERT refact */ { yymsp[-2].minor.yy497.value = 0; yymsp[-2].minor.yy497.mask = 0x000000; } break; - case 48: /* refarg ::= ON DELETE refact */ + case 47: /* refarg ::= ON DELETE refact */ { yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194; yymsp[-2].minor.yy497.mask = 0x0000ff; } break; - case 49: /* refarg ::= ON UPDATE refact */ + case 48: /* refarg ::= ON UPDATE refact */ { yymsp[-2].minor.yy497.value = yymsp[0].minor.yy194<<8; yymsp[-2].minor.yy497.mask = 0x00ff00; } break; - case 50: /* refact ::= SET NULL */ + case 49: /* refact ::= SET NULL */ { yymsp[-1].minor.yy194 = OE_SetNull; /* EV: R-33326-45252 */} break; - case 51: /* refact ::= SET DEFAULT */ + case 50: /* refact ::= SET DEFAULT */ { yymsp[-1].minor.yy194 = OE_SetDflt; /* EV: R-33326-45252 */} break; - case 52: /* refact ::= CASCADE */ + case 51: /* refact ::= CASCADE */ { yymsp[0].minor.yy194 = OE_Cascade; /* EV: R-33326-45252 */} break; - case 53: /* refact ::= RESTRICT */ + case 52: /* refact ::= RESTRICT */ { yymsp[0].minor.yy194 = OE_Restrict; /* EV: R-33326-45252 */} break; - case 54: /* refact ::= NO ACTION */ + case 53: /* refact ::= NO ACTION */ { yymsp[-1].minor.yy194 = OE_None; /* EV: R-33326-45252 */} break; - case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + case 54: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ {yymsp[-2].minor.yy194 = 0;} break; - case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); - case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); + case 55: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 70: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==70); + case 143: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==143); {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} break; - case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ - case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); - case 186: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==186); - case 189: /* in_op ::= NOT IN */ yytestcase(yyruleno==189); - case 215: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==215); + case 57: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ + case 74: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==74); + case 184: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==184); + case 187: /* in_op ::= NOT IN */ yytestcase(yyruleno==187); + case 213: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==213); {yymsp[-1].minor.yy194 = 1;} break; - case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + case 58: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ {yymsp[-1].minor.yy194 = 0;} break; - case 61: /* tconscomma ::= COMMA */ + case 60: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; - case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + case 62: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ {sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);} break; - case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */ + case 63: /* tcons ::= UNIQUE LP sortlist RP onconf */ {sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy148,yymsp[0].minor.yy194,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; - case 65: /* tcons ::= CHECK LP expr RP onconf */ + case 64: /* tcons ::= CHECK LP expr RP onconf */ {sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);} break; - case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + case 65: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194); sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194); } break; - case 68: /* onconf ::= */ - case 70: /* orconf ::= */ yytestcase(yyruleno==70); + case 67: /* onconf ::= */ + case 69: /* orconf ::= */ yytestcase(yyruleno==69); {yymsp[1].minor.yy194 = OE_Default;} break; - case 69: /* onconf ::= ON CONFLICT resolvetype */ + case 68: /* onconf ::= ON CONFLICT resolvetype */ {yymsp[-2].minor.yy194 = yymsp[0].minor.yy194;} break; - case 72: /* resolvetype ::= IGNORE */ + case 71: /* resolvetype ::= IGNORE */ {yymsp[0].minor.yy194 = OE_Ignore;} break; - case 73: /* resolvetype ::= REPLACE */ - case 145: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==145); + case 72: /* resolvetype ::= REPLACE */ + case 144: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==144); {yymsp[0].minor.yy194 = OE_Replace;} break; - case 74: /* cmd ::= DROP TABLE ifexists fullname */ + case 73: /* cmd ::= DROP TABLE ifexists fullname */ { sqlite3DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194); } break; - case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + case 76: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[0].minor.yy243, yymsp[-7].minor.yy194, yymsp[-5].minor.yy194); } break; - case 78: /* cmd ::= DROP VIEW ifexists fullname */ + case 77: /* cmd ::= DROP VIEW ifexists fullname */ { sqlite3DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194); } break; - case 79: /* cmd ::= select */ + case 78: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; sqlite3Select(pParse, yymsp[0].minor.yy243, &dest); sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy243); } break; - case 80: /* select ::= with selectnowith */ + case 79: /* select ::= with selectnowith */ { Select *p = yymsp[0].minor.yy243; if( p ){ @@ -137961,7 +139461,7 @@ static void yy_reduce( yymsp[-1].minor.yy243 = p; /*A-overwrites-W*/ } break; - case 81: /* selectnowith ::= selectnowith multiselect_op oneselect */ + case 80: /* selectnowith ::= selectnowith multiselect_op oneselect */ { Select *pRhs = yymsp[0].minor.yy243; Select *pLhs = yymsp[-2].minor.yy243; @@ -137985,14 +139485,14 @@ static void yy_reduce( yymsp[-2].minor.yy243 = pRhs; } break; - case 82: /* multiselect_op ::= UNION */ - case 84: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==84); + case 81: /* multiselect_op ::= UNION */ + case 83: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==83); {yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-OP*/} break; - case 83: /* multiselect_op ::= UNION ALL */ + case 82: /* multiselect_op ::= UNION ALL */ {yymsp[-1].minor.yy194 = TK_ALL;} break; - case 85: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + case 84: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { #if SELECTTRACE_ENABLED Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ @@ -138024,12 +139524,12 @@ static void yy_reduce( #endif /* SELECTRACE_ENABLED */ } break; - case 86: /* values ::= VALUES LP nexprlist RP */ + case 85: /* values ::= VALUES LP nexprlist RP */ { yymsp[-3].minor.yy243 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values,0,0); } break; - case 87: /* values ::= values COMMA LP exprlist RP */ + case 86: /* values ::= values COMMA LP exprlist RP */ { Select *pRight, *pLeft = yymsp[-4].minor.yy243; pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy148,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); @@ -138043,34 +139543,34 @@ static void yy_reduce( } } break; - case 88: /* distinct ::= DISTINCT */ + case 87: /* distinct ::= DISTINCT */ {yymsp[0].minor.yy194 = SF_Distinct;} break; - case 89: /* distinct ::= ALL */ + case 88: /* distinct ::= ALL */ {yymsp[0].minor.yy194 = SF_All;} break; - case 91: /* sclp ::= */ - case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); - case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); - case 202: /* exprlist ::= */ yytestcase(yyruleno==202); - case 205: /* paren_exprlist ::= */ yytestcase(yyruleno==205); - case 210: /* eidlist_opt ::= */ yytestcase(yyruleno==210); + case 90: /* sclp ::= */ + case 118: /* orderby_opt ::= */ yytestcase(yyruleno==118); + case 125: /* groupby_opt ::= */ yytestcase(yyruleno==125); + case 200: /* exprlist ::= */ yytestcase(yyruleno==200); + case 203: /* paren_exprlist ::= */ yytestcase(yyruleno==203); + case 208: /* eidlist_opt ::= */ yytestcase(yyruleno==208); {yymsp[1].minor.yy148 = 0;} break; - case 92: /* selcollist ::= sclp expr as */ + case 91: /* selcollist ::= sclp expr as */ { yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-2].minor.yy148, &yymsp[0].minor.yy0, 1); sqlite3ExprListSetSpan(pParse,yymsp[-2].minor.yy148,&yymsp[-1].minor.yy190); } break; - case 93: /* selcollist ::= sclp STAR */ + case 92: /* selcollist ::= sclp STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); } break; - case 94: /* selcollist ::= sclp nm DOT STAR */ + case 93: /* selcollist ::= sclp nm DOT STAR */ { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); @@ -138078,47 +139578,47 @@ static void yy_reduce( yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); } break; - case 95: /* as ::= AS nm */ - case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); - case 224: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==224); - case 225: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==225); + case 94: /* as ::= AS nm */ + case 105: /* dbnm ::= DOT nm */ yytestcase(yyruleno==105); + case 222: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==222); + case 223: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==223); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; - case 97: /* from ::= */ + case 96: /* from ::= */ {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} break; - case 98: /* from ::= FROM seltablist */ + case 97: /* from ::= FROM seltablist */ { yymsp[-1].minor.yy185 = yymsp[0].minor.yy185; sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy185); } break; - case 99: /* stl_prefix ::= seltablist joinop */ + case 98: /* stl_prefix ::= seltablist joinop */ { if( ALWAYS(yymsp[-1].minor.yy185 && yymsp[-1].minor.yy185->nSrc>0) ) yymsp[-1].minor.yy185->a[yymsp[-1].minor.yy185->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy194; } break; - case 100: /* stl_prefix ::= */ + case 99: /* stl_prefix ::= */ {yymsp[1].minor.yy185 = 0;} break; - case 101: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + case 100: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy185, &yymsp[-2].minor.yy0); } break; - case 102: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + case 101: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ { yymsp[-8].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy185,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy185, yymsp[-4].minor.yy148); } break; - case 103: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + case 102: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { yymsp[-6].minor.yy185 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254); } break; - case 104: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + case 103: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){ yymsp[-6].minor.yy185 = yymsp[-4].minor.yy185; @@ -138142,96 +139642,96 @@ static void yy_reduce( } } break; - case 105: /* dbnm ::= */ - case 114: /* indexed_opt ::= */ yytestcase(yyruleno==114); + case 104: /* dbnm ::= */ + case 113: /* indexed_opt ::= */ yytestcase(yyruleno==113); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 107: /* fullname ::= nm dbnm */ + case 106: /* fullname ::= nm dbnm */ {yymsp[-1].minor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 108: /* joinop ::= COMMA|JOIN */ + case 107: /* joinop ::= COMMA|JOIN */ { yymsp[0].minor.yy194 = JT_INNER; } break; - case 109: /* joinop ::= JOIN_KW JOIN */ + case 108: /* joinop ::= JOIN_KW JOIN */ {yymsp[-1].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; - case 110: /* joinop ::= JOIN_KW nm JOIN */ + case 109: /* joinop ::= JOIN_KW nm JOIN */ {yymsp[-2].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; - case 111: /* joinop ::= JOIN_KW nm nm JOIN */ + case 110: /* joinop ::= JOIN_KW nm nm JOIN */ {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; - case 112: /* on_opt ::= ON expr */ - case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); - case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); - case 198: /* case_else ::= ELSE expr */ yytestcase(yyruleno==198); + case 111: /* on_opt ::= ON expr */ + case 128: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==128); + case 135: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==135); + case 196: /* case_else ::= ELSE expr */ yytestcase(yyruleno==196); {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} break; - case 113: /* on_opt ::= */ - case 128: /* having_opt ::= */ yytestcase(yyruleno==128); - case 135: /* where_opt ::= */ yytestcase(yyruleno==135); - case 199: /* case_else ::= */ yytestcase(yyruleno==199); - case 201: /* case_operand ::= */ yytestcase(yyruleno==201); + case 112: /* on_opt ::= */ + case 127: /* having_opt ::= */ yytestcase(yyruleno==127); + case 134: /* where_opt ::= */ yytestcase(yyruleno==134); + case 197: /* case_else ::= */ yytestcase(yyruleno==197); + case 199: /* case_operand ::= */ yytestcase(yyruleno==199); {yymsp[1].minor.yy72 = 0;} break; - case 115: /* indexed_opt ::= INDEXED BY nm */ + case 114: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 116: /* indexed_opt ::= NOT INDEXED */ + case 115: /* indexed_opt ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 117: /* using_opt ::= USING LP idlist RP */ + case 116: /* using_opt ::= USING LP idlist RP */ {yymsp[-3].minor.yy254 = yymsp[-1].minor.yy254;} break; - case 118: /* using_opt ::= */ - case 146: /* idlist_opt ::= */ yytestcase(yyruleno==146); + case 117: /* using_opt ::= */ + case 145: /* idlist_opt ::= */ yytestcase(yyruleno==145); {yymsp[1].minor.yy254 = 0;} break; - case 120: /* orderby_opt ::= ORDER BY sortlist */ - case 127: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==127); + case 119: /* orderby_opt ::= ORDER BY sortlist */ + case 126: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==126); {yymsp[-2].minor.yy148 = yymsp[0].minor.yy148;} break; - case 121: /* sortlist ::= sortlist COMMA expr sortorder */ + case 120: /* sortlist ::= sortlist COMMA expr sortorder */ { yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy190.pExpr); sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy148,yymsp[0].minor.yy194); } break; - case 122: /* sortlist ::= expr sortorder */ + case 121: /* sortlist ::= expr sortorder */ { yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy190.pExpr); /*A-overwrites-Y*/ sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy148,yymsp[0].minor.yy194); } break; - case 123: /* sortorder ::= ASC */ + case 122: /* sortorder ::= ASC */ {yymsp[0].minor.yy194 = SQLITE_SO_ASC;} break; - case 124: /* sortorder ::= DESC */ + case 123: /* sortorder ::= DESC */ {yymsp[0].minor.yy194 = SQLITE_SO_DESC;} break; - case 125: /* sortorder ::= */ + case 124: /* sortorder ::= */ {yymsp[1].minor.yy194 = SQLITE_SO_UNDEFINED;} break; - case 130: /* limit_opt ::= */ + case 129: /* limit_opt ::= */ {yymsp[1].minor.yy354.pLimit = 0; yymsp[1].minor.yy354.pOffset = 0;} break; - case 131: /* limit_opt ::= LIMIT expr */ + case 130: /* limit_opt ::= LIMIT expr */ {yymsp[-1].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr; yymsp[-1].minor.yy354.pOffset = 0;} break; - case 132: /* limit_opt ::= LIMIT expr OFFSET expr */ + case 131: /* limit_opt ::= LIMIT expr OFFSET expr */ {yymsp[-3].minor.yy354.pLimit = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pOffset = yymsp[0].minor.yy190.pExpr;} break; - case 133: /* limit_opt ::= LIMIT expr COMMA expr */ + case 132: /* limit_opt ::= LIMIT expr COMMA expr */ {yymsp[-3].minor.yy354.pOffset = yymsp[-2].minor.yy190.pExpr; yymsp[-3].minor.yy354.pLimit = yymsp[0].minor.yy190.pExpr;} break; - case 134: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ + case 133: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ { sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0); sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72); } break; - case 137: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ + case 136: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ { sqlite3WithPush(pParse, yymsp[-7].minor.yy285, 1); sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0); @@ -138239,63 +139739,58 @@ static void yy_reduce( sqlite3Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy194); } break; - case 138: /* setlist ::= setlist COMMA nm EQ expr */ + case 137: /* setlist ::= setlist COMMA nm EQ expr */ { yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, 1); } break; - case 139: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + case 138: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { yymsp[-6].minor.yy148 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy148, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); } break; - case 140: /* setlist ::= nm EQ expr */ + case 139: /* setlist ::= nm EQ expr */ { yylhsminor.yy148 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr); sqlite3ExprListSetName(pParse, yylhsminor.yy148, &yymsp[-2].minor.yy0, 1); } yymsp[-2].minor.yy148 = yylhsminor.yy148; break; - case 141: /* setlist ::= LP idlist RP EQ expr */ + case 140: /* setlist ::= LP idlist RP EQ expr */ { yymsp[-4].minor.yy148 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy190.pExpr); } break; - case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ + case 141: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ { sqlite3WithPush(pParse, yymsp[-5].minor.yy285, 1); sqlite3Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy194); } break; - case 143: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ { sqlite3WithPush(pParse, yymsp[-6].minor.yy285, 1); sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194); } break; - case 147: /* idlist_opt ::= LP idlist RP */ + case 146: /* idlist_opt ::= LP idlist RP */ {yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} break; - case 148: /* idlist ::= idlist COMMA nm */ + case 147: /* idlist ::= idlist COMMA nm */ {yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} break; - case 149: /* idlist ::= nm */ + case 148: /* idlist ::= nm */ {yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; - case 150: /* expr ::= LP expr RP */ + case 149: /* expr ::= LP expr RP */ {spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr;} break; - case 151: /* term ::= NULL */ - case 156: /* term ::= FLOAT|BLOB */ yytestcase(yyruleno==156); - case 157: /* term ::= STRING */ yytestcase(yyruleno==157); -{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0);/*A-overwrites-X*/} - break; - case 152: /* expr ::= ID|INDEXED */ - case 153: /* expr ::= JOIN_KW */ yytestcase(yyruleno==153); + case 150: /* expr ::= ID|INDEXED */ + case 151: /* expr ::= JOIN_KW */ yytestcase(yyruleno==151); {spanExpr(&yymsp[0].minor.yy190,pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 154: /* expr ::= nm DOT nm */ + case 152: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); @@ -138303,7 +139798,7 @@ static void yy_reduce( yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } break; - case 155: /* expr ::= nm DOT nm DOT nm */ + case 153: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); @@ -138313,16 +139808,19 @@ static void yy_reduce( yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } break; - case 158: /* term ::= INTEGER */ + case 154: /* term ::= NULL|FLOAT|BLOB */ + case 155: /* term ::= STRING */ yytestcase(yyruleno==155); +{spanExpr(&yymsp[0].minor.yy190,pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 156: /* term ::= INTEGER */ { yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; - if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf|EP_Resolved; } yymsp[0].minor.yy190 = yylhsminor.yy190; break; - case 159: /* expr ::= VARIABLE */ + case 157: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; @@ -138345,20 +139843,20 @@ static void yy_reduce( } } break; - case 160: /* expr ::= expr COLLATE ID|STRING */ + case 158: /* expr ::= expr COLLATE ID|STRING */ { yymsp[-2].minor.yy190.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0, 1); yymsp[-2].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 161: /* expr ::= CAST LP expr AS typetoken RP */ + case 159: /* expr ::= CAST LP expr AS typetoken RP */ { spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0); } break; - case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 160: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); @@ -138371,21 +139869,21 @@ static void yy_reduce( } yymsp[-4].minor.yy190 = yylhsminor.yy190; break; - case 163: /* expr ::= ID|INDEXED LP STAR RP */ + case 161: /* expr ::= ID|INDEXED LP STAR RP */ { yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); spanSet(&yylhsminor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } yymsp[-3].minor.yy190 = yylhsminor.yy190; break; - case 164: /* term ::= CTIME_KW */ + case 162: /* term ::= CTIME_KW */ { yylhsminor.yy190.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); spanSet(&yylhsminor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } yymsp[0].minor.yy190 = yylhsminor.yy190; break; - case 165: /* expr ::= LP nexprlist COMMA expr RP */ + case 163: /* expr ::= LP nexprlist COMMA expr RP */ { ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); @@ -138398,20 +139896,20 @@ static void yy_reduce( } yymsp[-4].minor.yy190 = yylhsminor.yy190; break; - case 166: /* expr ::= expr AND expr */ - case 167: /* expr ::= expr OR expr */ yytestcase(yyruleno==167); - case 168: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==168); - case 169: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==169); - case 170: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==170); - case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); - case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); - case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); + case 164: /* expr ::= expr AND expr */ + case 165: /* expr ::= expr OR expr */ yytestcase(yyruleno==165); + case 166: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==166); + case 167: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==167); + case 168: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==168); + case 169: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==169); + case 170: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==170); + case 171: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==171); {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} break; - case 174: /* likeop ::= NOT LIKE_KW|MATCH */ + case 172: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 175: /* expr ::= expr likeop expr */ + case 173: /* expr ::= expr likeop expr */ { ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; @@ -138424,7 +139922,7 @@ static void yy_reduce( if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 176: /* expr ::= expr likeop expr ESCAPE expr */ + case 174: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; @@ -138438,39 +139936,39 @@ static void yy_reduce( if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 177: /* expr ::= expr ISNULL|NOTNULL */ + case 175: /* expr ::= expr ISNULL|NOTNULL */ {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} break; - case 178: /* expr ::= expr NOT NULL */ + case 176: /* expr ::= expr NOT NULL */ {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} break; - case 179: /* expr ::= expr IS expr */ + case 177: /* expr ::= expr IS expr */ { spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); } break; - case 180: /* expr ::= expr IS NOT expr */ + case 178: /* expr ::= expr IS NOT expr */ { spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); } break; - case 181: /* expr ::= NOT expr */ - case 182: /* expr ::= BITNOT expr */ yytestcase(yyruleno==182); + case 179: /* expr ::= NOT expr */ + case 180: /* expr ::= BITNOT expr */ yytestcase(yyruleno==180); {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 183: /* expr ::= MINUS expr */ + case 181: /* expr ::= MINUS expr */ {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 184: /* expr ::= PLUS expr */ + case 182: /* expr ::= PLUS expr */ {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 185: /* between_op ::= BETWEEN */ - case 188: /* in_op ::= IN */ yytestcase(yyruleno==188); + case 183: /* between_op ::= BETWEEN */ + case 186: /* in_op ::= IN */ yytestcase(yyruleno==186); {yymsp[0].minor.yy194 = 0;} break; - case 187: /* expr ::= expr between_op expr AND expr */ + case 185: /* expr ::= expr between_op expr AND expr */ { ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); @@ -138484,7 +139982,7 @@ static void yy_reduce( yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; } break; - case 190: /* expr ::= expr in_op LP exprlist RP */ + case 188: /* expr ::= expr in_op LP exprlist RP */ { if( yymsp[-1].minor.yy148==0 ){ /* Expressions of the form @@ -138537,14 +140035,14 @@ static void yy_reduce( yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 191: /* expr ::= LP select RP */ + case 189: /* expr ::= LP select RP */ { spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); } break; - case 192: /* expr ::= expr in_op LP select RP */ + case 190: /* expr ::= expr in_op LP select RP */ { yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); @@ -138552,7 +140050,7 @@ static void yy_reduce( yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 193: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 191: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); @@ -138563,7 +140061,7 @@ static void yy_reduce( yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; } break; - case 194: /* expr ::= EXISTS LP select RP */ + case 192: /* expr ::= EXISTS LP select RP */ { Expr *p; spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ @@ -138571,7 +140069,7 @@ static void yy_reduce( sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); } break; - case 195: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 193: /* expr ::= CASE case_operand case_exprlist case_else END */ { spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); @@ -138584,80 +140082,80 @@ static void yy_reduce( } } break; - case 196: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 194: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); } break; - case 197: /* case_exprlist ::= WHEN expr THEN expr */ + case 195: /* case_exprlist ::= WHEN expr THEN expr */ { yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); } break; - case 200: /* case_operand ::= expr */ + case 198: /* case_operand ::= expr */ {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} break; - case 203: /* nexprlist ::= nexprlist COMMA expr */ + case 201: /* nexprlist ::= nexprlist COMMA expr */ {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} break; - case 204: /* nexprlist ::= expr */ + case 202: /* nexprlist ::= expr */ {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} break; - case 206: /* paren_exprlist ::= LP exprlist RP */ - case 211: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==211); + case 204: /* paren_exprlist ::= LP exprlist RP */ + case 209: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==209); {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} break; - case 207: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 205: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); } break; - case 208: /* uniqueflag ::= UNIQUE */ - case 249: /* raisetype ::= ABORT */ yytestcase(yyruleno==249); + case 206: /* uniqueflag ::= UNIQUE */ + case 246: /* raisetype ::= ABORT */ yytestcase(yyruleno==246); {yymsp[0].minor.yy194 = OE_Abort;} break; - case 209: /* uniqueflag ::= */ + case 207: /* uniqueflag ::= */ {yymsp[1].minor.yy194 = OE_None;} break; - case 212: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 210: /* eidlist ::= eidlist COMMA nm collate sortorder */ { yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); } break; - case 213: /* eidlist ::= nm collate sortorder */ + case 211: /* eidlist ::= nm collate sortorder */ { yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ } break; - case 216: /* cmd ::= DROP INDEX ifexists fullname */ + case 214: /* cmd ::= DROP INDEX ifexists fullname */ {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} break; - case 217: /* cmd ::= VACUUM */ + case 215: /* cmd ::= VACUUM */ {sqlite3Vacuum(pParse,0);} break; - case 218: /* cmd ::= VACUUM nm */ + case 216: /* cmd ::= VACUUM nm */ {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} break; - case 219: /* cmd ::= PRAGMA nm dbnm */ + case 217: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 220: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 218: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 221: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 219: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 222: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 220: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 223: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 221: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 226: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 224: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; @@ -138665,53 +140163,50 @@ static void yy_reduce( sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); } break; - case 227: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 225: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 228: /* trigger_time ::= BEFORE */ -{ yymsp[0].minor.yy194 = TK_BEFORE; } - break; - case 229: /* trigger_time ::= AFTER */ -{ yymsp[0].minor.yy194 = TK_AFTER; } + case 226: /* trigger_time ::= BEFORE|AFTER */ +{ yymsp[0].minor.yy194 = yymsp[0].major; /*A-overwrites-X*/ } break; - case 230: /* trigger_time ::= INSTEAD OF */ + case 227: /* trigger_time ::= INSTEAD OF */ { yymsp[-1].minor.yy194 = TK_INSTEAD;} break; - case 231: /* trigger_time ::= */ + case 228: /* trigger_time ::= */ { yymsp[1].minor.yy194 = TK_BEFORE; } break; - case 232: /* trigger_event ::= DELETE|INSERT */ - case 233: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==233); + case 229: /* trigger_event ::= DELETE|INSERT */ + case 230: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==230); {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} break; - case 234: /* trigger_event ::= UPDATE OF idlist */ + case 231: /* trigger_event ::= UPDATE OF idlist */ {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} break; - case 235: /* when_clause ::= */ - case 254: /* key_opt ::= */ yytestcase(yyruleno==254); + case 232: /* when_clause ::= */ + case 251: /* key_opt ::= */ yytestcase(yyruleno==251); { yymsp[1].minor.yy72 = 0; } break; - case 236: /* when_clause ::= WHEN expr */ - case 255: /* key_opt ::= KEY expr */ yytestcase(yyruleno==255); + case 233: /* when_clause ::= WHEN expr */ + case 252: /* key_opt ::= KEY expr */ yytestcase(yyruleno==252); { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } break; - case 237: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 234: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { assert( yymsp[-2].minor.yy145!=0 ); yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 238: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 235: /* trigger_cmd_list ::= trigger_cmd SEMI */ { assert( yymsp[-1].minor.yy145!=0 ); yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 239: /* trnm ::= nm DOT nm */ + case 236: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -138719,33 +140214,33 @@ static void yy_reduce( "statements within triggers"); } break; - case 240: /* tridxby ::= INDEXED BY nm */ + case 237: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 241: /* tridxby ::= NOT INDEXED */ + case 238: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 242: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ + case 239: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} break; - case 243: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ + case 240: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} break; - case 244: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ + case 241: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} break; - case 245: /* trigger_cmd ::= select */ + case 242: /* trigger_cmd ::= select */ {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} break; - case 246: /* expr ::= RAISE LP IGNORE RP */ + case 243: /* expr ::= RAISE LP IGNORE RP */ { spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); @@ -138754,7 +140249,7 @@ static void yy_reduce( } } break; - case 247: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 244: /* expr ::= RAISE LP raisetype COMMA nm RP */ { spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); @@ -138763,172 +140258,176 @@ static void yy_reduce( } } break; - case 248: /* raisetype ::= ROLLBACK */ + case 245: /* raisetype ::= ROLLBACK */ {yymsp[0].minor.yy194 = OE_Rollback;} break; - case 250: /* raisetype ::= FAIL */ + case 247: /* raisetype ::= FAIL */ {yymsp[0].minor.yy194 = OE_Fail;} break; - case 251: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 248: /* cmd ::= DROP TRIGGER ifexists fullname */ { sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); } break; - case 252: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 249: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); } break; - case 253: /* cmd ::= DETACH database_kw_opt expr */ + case 250: /* cmd ::= DETACH database_kw_opt expr */ { sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); } break; - case 256: /* cmd ::= REINDEX */ + case 253: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 257: /* cmd ::= REINDEX nm dbnm */ + case 254: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 258: /* cmd ::= ANALYZE */ + case 255: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 259: /* cmd ::= ANALYZE nm dbnm */ + case 256: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 260: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 257: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); } break; - case 261: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 258: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 262: /* add_column_fullname ::= fullname */ + case 259: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); } break; - case 263: /* cmd ::= create_vtab */ + case 260: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 264: /* cmd ::= create_vtab LP vtabarglist RP */ + case 261: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 265: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 262: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); } break; - case 266: /* vtabarg ::= */ + case 263: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 267: /* vtabargtoken ::= ANY */ - case 268: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==268); - case 269: /* lp ::= LP */ yytestcase(yyruleno==269); + case 264: /* vtabargtoken ::= ANY */ + case 265: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==265); + case 266: /* lp ::= LP */ yytestcase(yyruleno==266); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 270: /* with ::= */ + case 267: /* with ::= */ {yymsp[1].minor.yy285 = 0;} break; - case 271: /* with ::= WITH wqlist */ + case 268: /* with ::= WITH wqlist */ { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } break; - case 272: /* with ::= WITH RECURSIVE wqlist */ + case 269: /* with ::= WITH RECURSIVE wqlist */ { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } break; - case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 270: /* wqlist ::= nm eidlist_opt AS LP select RP */ { yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ } break; - case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 271: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); } break; default: - /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); - /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); - /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); - /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); - /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); - /* (280) explain ::= */ yytestcase(yyruleno==280); - /* (281) trans_opt ::= */ yytestcase(yyruleno==281); - /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); - /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); - /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); - /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); - /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); - /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); - /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); - /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); - /* (290) nm ::= STRING */ yytestcase(yyruleno==290); - /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); - /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); - /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); - /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); - /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); - /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); - /* (297) carglist ::= */ yytestcase(yyruleno==297); - /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); - /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); - /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); - /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); - /* (302) tconscomma ::= */ yytestcase(yyruleno==302); - /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); - /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); - /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); - /* (306) oneselect ::= values */ yytestcase(yyruleno==306); - /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); - /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); - /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); - /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310); - /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); - /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); - /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); - /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); - /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); - /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316); - /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317); - /* (318) foreach_clause ::= */ yytestcase(yyruleno==318); - /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319); - /* (320) trnm ::= nm */ yytestcase(yyruleno==320); - /* (321) tridxby ::= */ yytestcase(yyruleno==321); - /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322); - /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323); - /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324); - /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325); - /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326); - /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327); - /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328); - /* (329) anylist ::= */ yytestcase(yyruleno==329); - /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330); - /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331); + /* (272) input ::= cmdlist */ yytestcase(yyruleno==272); + /* (273) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==273); + /* (274) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=274); + /* (275) ecmd ::= SEMI */ yytestcase(yyruleno==275); + /* (276) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==276); + /* (277) explain ::= */ yytestcase(yyruleno==277); + /* (278) trans_opt ::= */ yytestcase(yyruleno==278); + /* (279) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==279); + /* (280) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==280); + /* (281) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==281); + /* (282) savepoint_opt ::= */ yytestcase(yyruleno==282); + /* (283) cmd ::= create_table create_table_args */ yytestcase(yyruleno==283); + /* (284) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==284); + /* (285) columnlist ::= columnname carglist */ yytestcase(yyruleno==285); + /* (286) nm ::= ID|INDEXED */ yytestcase(yyruleno==286); + /* (287) nm ::= STRING */ yytestcase(yyruleno==287); + /* (288) nm ::= JOIN_KW */ yytestcase(yyruleno==288); + /* (289) typetoken ::= typename */ yytestcase(yyruleno==289); + /* (290) typename ::= ID|STRING */ yytestcase(yyruleno==290); + /* (291) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=291); + /* (292) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=292); + /* (293) carglist ::= carglist ccons */ yytestcase(yyruleno==293); + /* (294) carglist ::= */ yytestcase(yyruleno==294); + /* (295) ccons ::= NULL onconf */ yytestcase(yyruleno==295); + /* (296) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==296); + /* (297) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==297); + /* (298) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=298); + /* (299) tconscomma ::= */ yytestcase(yyruleno==299); + /* (300) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=300); + /* (301) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=301); + /* (302) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=302); + /* (303) oneselect ::= values */ yytestcase(yyruleno==303); + /* (304) sclp ::= selcollist COMMA */ yytestcase(yyruleno==304); + /* (305) as ::= ID|STRING */ yytestcase(yyruleno==305); + /* (306) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=306); + /* (307) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==307); + /* (308) exprlist ::= nexprlist */ yytestcase(yyruleno==308); + /* (309) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=309); + /* (310) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=310); + /* (311) nmnum ::= ON */ yytestcase(yyruleno==311); + /* (312) nmnum ::= DELETE */ yytestcase(yyruleno==312); + /* (313) nmnum ::= DEFAULT */ yytestcase(yyruleno==313); + /* (314) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==314); + /* (315) foreach_clause ::= */ yytestcase(yyruleno==315); + /* (316) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==316); + /* (317) trnm ::= nm */ yytestcase(yyruleno==317); + /* (318) tridxby ::= */ yytestcase(yyruleno==318); + /* (319) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==319); + /* (320) database_kw_opt ::= */ yytestcase(yyruleno==320); + /* (321) kwcolumn_opt ::= */ yytestcase(yyruleno==321); + /* (322) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==322); + /* (323) vtabarglist ::= vtabarg */ yytestcase(yyruleno==323); + /* (324) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==324); + /* (325) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==325); + /* (326) anylist ::= */ yytestcase(yyruleno==326); + /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); + /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); break; /********** End reduce actions ************************************************/ }; assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) ); yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; - yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact>YY_MAX_SHIFT ){ - yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - } - yymsp -= yysize-1; + yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto); + + /* There are no SHIFTREDUCE actions on nonterminals because the table + ** generator has simplified them to pure REDUCE actions. */ + assert( !(yyact>YY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) ); + + /* It is not possible for a REDUCE to be followed by an error */ + assert( yyact!=YY_ERROR_ACTION ); + + if( yyact==YY_ACCEPT_ACTION ){ + yypParser->yytos += yysize; + yy_accept(yypParser); + }else{ + yymsp += yysize+1; yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yyTraceShift(yypParser, yyact); - }else{ - assert( yyact == YY_ACCEPT_ACTION ); - yypParser->yytos -= yysize; - yy_accept(yypParser); } } @@ -139334,134 +140833,145 @@ const unsigned char ebcdicToAscii[] = { ** on platforms with limited memory. */ /* Hash score: 182 */ +/* zKWText[] encodes 834 bytes of keyword text in 554 bytes */ +/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ +/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ +/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ +/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */ +/* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ +/* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */ +/* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */ +/* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */ +/* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */ +/* VACUUMVIEWINITIALLY */ +static const char zKWText[553] = { + 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', + 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', + 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', + 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F', + 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N', + 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I', + 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E', + 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E', + 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T', + 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', + 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', + 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', + 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E', + 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A', + 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A', + 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A', + 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J', + 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L', + 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E', + 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H', + 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E', + 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E', + 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M', + 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R', + 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A', + 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', + 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O', + 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T', + 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R', + 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M', + 'V','I','E','W','I','N','I','T','I','A','L','L','Y', +}; +/* aKWHash[i] is the hash value for the i-th keyword */ +static const unsigned char aKWHash[127] = { + 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0, + 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0, + 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71, + 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44, + 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25, + 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0, + 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14, + 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113, + 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0, + 29, 0, 86, 63, 64, 0, 20, 61, 0, 56, +}; +/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0 +** then the i-th keyword has no more hash collisions. Otherwise, +** the next keyword with the same hash is aKWHash[i]-1. */ +static const unsigned char aKWNext[124] = { + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, + 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38, + 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0, + 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34, + 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8, + 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37, + 73, 83, 0, 35, 68, 0, 0, +}; +/* aKWLen[i] is the length (in bytes) of the i-th keyword */ +static const unsigned char aKWLen[124] = { + 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, + 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, + 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, + 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, + 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4, + 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, + 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, + 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, + 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8, + 3, 5, 5, 6, 4, 9, 3, +}; +/* aKWOffset[i] is the index into zKWText[] of the start of +** the text for the i-th keyword. */ +static const unsigned short int aKWOffset[124] = { + 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, + 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, + 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, + 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, + 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246, + 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318, + 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380, + 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459, + 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513, + 521, 524, 529, 534, 540, 544, 549, +}; +/* aKWCode[i] is the parser symbol code for the i-th keyword */ +static const unsigned char aKWCode[124] = { + TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, + TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, + TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, + TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, + TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, + TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, + TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, + TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, + TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, + TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, + TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, + TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, + TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, + TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, + TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, + TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, + TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, + TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, + TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, + TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, + TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, + TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, + TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, + TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, + TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, +}; +/* Check to see if z[0..n-1] is a keyword. If it is, write the +** parser symbol code for that keyword into *pType. Always +** return the integer n (the length of the token). */ static int keywordCode(const char *z, int n, int *pType){ - /* zText[] encodes 834 bytes of keywords in 554 bytes */ - /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ - /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ - /* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ - /* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */ - /* BETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ - /* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */ - /* WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */ - /* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */ - /* FROMFULLGLOBYIFISNULLORDERESTRICTRIGHTROLLBACKROWUNIONUSING */ - /* VACUUMVIEWINITIALLY */ - static const char zText[553] = { - 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', - 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', - 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', - 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F', - 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N', - 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I', - 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E', - 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E', - 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T', - 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', - 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', - 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', - 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E', - 'B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C','A', - 'S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L','A', - 'T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A', - 'T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E','J', - 'O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A','L', - 'Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U','E', - 'S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W','H', - 'E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C','E', - 'A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E', - 'M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M', - 'I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R', - 'R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A', - 'R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', - 'R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O', - 'B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T', - 'R','I','C','T','R','I','G','H','T','R','O','L','L','B','A','C','K','R', - 'O','W','U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M', - 'V','I','E','W','I','N','I','T','I','A','L','L','Y', - }; - static const unsigned char aHash[127] = { - 76, 105, 117, 74, 0, 45, 0, 0, 82, 0, 77, 0, 0, - 42, 12, 78, 15, 0, 116, 85, 54, 112, 0, 19, 0, 0, - 121, 0, 119, 115, 0, 22, 93, 0, 9, 0, 0, 70, 71, - 0, 69, 6, 0, 48, 90, 102, 0, 118, 101, 0, 0, 44, - 0, 103, 24, 0, 17, 0, 122, 53, 23, 0, 5, 110, 25, - 96, 0, 0, 124, 106, 60, 123, 57, 28, 55, 0, 91, 0, - 100, 26, 0, 99, 0, 0, 0, 95, 92, 97, 88, 109, 14, - 39, 108, 0, 81, 0, 18, 89, 111, 32, 0, 120, 80, 113, - 62, 46, 84, 0, 0, 94, 40, 59, 114, 0, 36, 0, 0, - 29, 0, 86, 63, 64, 0, 20, 61, 0, 56, - }; - static const unsigned char aNext[124] = { - 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, - 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, - 0, 43, 3, 47, 0, 0, 0, 0, 30, 0, 58, 0, 38, - 0, 0, 0, 1, 66, 0, 0, 67, 0, 41, 0, 0, 0, - 0, 0, 0, 49, 65, 0, 0, 0, 0, 31, 52, 16, 34, - 10, 0, 0, 0, 0, 0, 0, 0, 11, 72, 79, 0, 8, - 0, 104, 98, 0, 107, 0, 87, 0, 75, 51, 0, 27, 37, - 73, 83, 0, 35, 68, 0, 0, - }; - static const unsigned char aLen[124] = { - 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, - 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, - 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, - 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, - 6, 6, 5, 6, 5, 5, 9, 7, 7, 3, 2, 4, 4, - 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, - 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, - 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, - 2, 4, 4, 4, 4, 4, 2, 2, 6, 5, 8, 5, 8, - 3, 5, 5, 6, 4, 9, 3, - }; - static const unsigned short int aOffset[124] = { - 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, - 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, - 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, - 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, - 199, 204, 209, 212, 218, 221, 225, 234, 240, 240, 240, 243, 246, - 250, 251, 255, 261, 265, 272, 278, 290, 296, 305, 307, 313, 318, - 320, 327, 332, 337, 343, 349, 354, 358, 361, 367, 371, 378, 380, - 387, 389, 391, 400, 404, 410, 416, 424, 429, 429, 445, 452, 459, - 460, 467, 471, 475, 479, 483, 486, 488, 490, 496, 500, 508, 513, - 521, 524, 529, 534, 540, 544, 549, - }; - static const unsigned char aCode[124] = { - TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, - TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, - TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, - TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, - TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, - TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, - TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, - TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, - TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, - TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, - TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, - TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN, - TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, - TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, - TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, - TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, - TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, - TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, - TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, - TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, - TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, - TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, - TK_BY, TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, - TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING, - TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL, - }; int i, j; const char *zKW; if( n>=2 ){ i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127; - for(i=((int)aHash[i])-1; i>=0; i=((int)aNext[i])-1){ - if( aLen[i]!=n ) continue; + for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){ + if( aKWLen[i]!=n ) continue; j = 0; - zKW = &zText[aOffset[i]]; + zKW = &zKWText[aKWOffset[i]]; #ifdef SQLITE_ASCII while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; } #endif @@ -139593,7 +141103,7 @@ static int keywordCode(const char *z, int n, int *pType){ testcase( i==121 ); /* VIEW */ testcase( i==122 ); /* INITIALLY */ testcase( i==123 ); /* ALL */ - *pType = aCode[i]; + *pType = aKWCode[i]; break; } } @@ -140496,6 +142006,9 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db); #ifdef SQLITE_ENABLE_JSON1 SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*); #endif +#ifdef SQLITE_ENABLE_STMTVTAB +SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*); +#endif #ifdef SQLITE_ENABLE_FTS5 SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); #endif @@ -140512,11 +142025,13 @@ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; */ SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } -/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a +/* IMPLEMENTATION-OF: R-25063-23286 The sqlite3_sourceid() function returns a ** pointer to a string constant whose value is the same as the -** SQLITE_SOURCE_ID C preprocessor macro. +** SQLITE_SOURCE_ID C preprocessor macro. Except if SQLite is built using +** an edited copy of the amalgamation, then the last four characters of +** the hash might be different from SQLITE_SOURCE_ID. */ -SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +/* SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } */ /* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function ** returns an integer equal to SQLITE_VERSION_NUMBER. @@ -140901,14 +142416,8 @@ SQLITE_API int sqlite3_config(int op, ...){ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } - case SQLITE_CONFIG_SCRATCH: { - /* EVIDENCE-OF: R-08404-60887 There are three arguments to - ** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from - ** which the scratch allocations will be drawn, the size of each scratch - ** allocation (sz), and the maximum number of scratch allocations (N). */ - sqlite3GlobalConfig.pScratch = va_arg(ap, void*); - sqlite3GlobalConfig.szScratch = va_arg(ap, int); - sqlite3GlobalConfig.nScratch = va_arg(ap, int); + case SQLITE_CONFIG_SMALL_MALLOC: { + sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int); break; } case SQLITE_CONFIG_PAGECACHE: { @@ -141129,7 +142638,8 @@ SQLITE_API int sqlite3_config(int op, ...){ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ #ifndef SQLITE_OMIT_LOOKASIDE void *pStart; - if( db->lookaside.nOut ){ + + if( sqlite3LookasideUsed(db,0)>0 ){ return SQLITE_BUSY; } /* Free any existing lookaside buffer for this handle before @@ -141157,16 +142667,18 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ pStart = pBuf; } db->lookaside.pStart = pStart; + db->lookaside.pInit = 0; db->lookaside.pFree = 0; db->lookaside.sz = (u16)sz; if( pStart ){ int i; LookasideSlot *p; assert( sz > (int)sizeof(LookasideSlot*) ); + db->lookaside.nSlot = cnt; p = (LookasideSlot*)pStart; for(i=cnt-1; i>=0; i--){ - p->pNext = db->lookaside.pFree; - db->lookaside.pFree = p; + p->pNext = db->lookaside.pInit; + db->lookaside.pInit = p; p = (LookasideSlot*)&((u8*)p)[sz]; } db->lookaside.pEnd = p; @@ -141177,6 +142689,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ db->lookaside.pEnd = db; db->lookaside.bDisable = 1; db->lookaside.bMalloced = 0; + db->lookaside.nSlot = 0; } #endif /* SQLITE_OMIT_LOOKASIDE */ return SQLITE_OK; @@ -141258,6 +142771,8 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ va_start(ap, op); switch( op ){ case SQLITE_DBCONFIG_MAINDBNAME: { + /* IMP: R-06824-28531 */ + /* IMP: R-36257-52125 */ db->aDb[0].zDbSName = va_arg(ap,char*); rc = SQLITE_OK; break; @@ -141279,6 +142794,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, + { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -141286,7 +142802,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ if( aFlagOp[i].op==op ){ int onoff = va_arg(ap, int); int *pRes = va_arg(ap, int*); - int oldFlags = db->flags; + u32 oldFlags = db->flags; if( onoff>0 ){ db->flags |= aFlagOp[i].mask; }else if( onoff==0 ){ @@ -141335,6 +142851,7 @@ static int binCollFunc( /* EVIDENCE-OF: R-65033-28449 The built-in BINARY collation compares ** strings byte by byte using the memcmp() function from the standard C ** library. */ + assert( pKey1 && pKey2 ); rc = memcmp(pKey1, pKey2, n); if( rc==0 ){ if( padFlag @@ -141692,7 +143209,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ sqlite3_mutex_leave(db->mutex); db->magic = SQLITE_MAGIC_CLOSED; sqlite3_mutex_free(db->mutex); - assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */ + assert( sqlite3LookasideUsed(db,0)==0 ); if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } @@ -141720,7 +143237,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** the database rollback and schema reset, which can cause false ** corruption reports in some cases. */ sqlite3BtreeEnterAll(db); - schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0; + schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0; for(i=0; i<db->nDb; i++){ Btree *p = db->aDb[i].pBt; @@ -141734,7 +143251,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); - if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ + if( (db->mDbFlags&DBFLAG_SchemaChange)!=0 && db->init.busy==0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } @@ -141867,10 +143384,10 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ static const char* const aMsg[] = { /* SQLITE_OK */ "not an error", - /* SQLITE_ERROR */ "SQL logic error or missing database", + /* SQLITE_ERROR */ "SQL logic error", /* SQLITE_INTERNAL */ 0, /* SQLITE_PERM */ "access permission denied", - /* SQLITE_ABORT */ "callback requested query abort", + /* SQLITE_ABORT */ "query aborted", /* SQLITE_BUSY */ "database is locked", /* SQLITE_LOCKED */ "database table is locked", /* SQLITE_NOMEM */ "out of memory", @@ -141882,17 +143399,21 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ /* SQLITE_FULL */ "database or disk is full", /* SQLITE_CANTOPEN */ "unable to open database file", /* SQLITE_PROTOCOL */ "locking protocol", - /* SQLITE_EMPTY */ "table contains no data", + /* SQLITE_EMPTY */ 0, /* SQLITE_SCHEMA */ "database schema has changed", /* SQLITE_TOOBIG */ "string or blob too big", /* SQLITE_CONSTRAINT */ "constraint failed", /* SQLITE_MISMATCH */ "datatype mismatch", - /* SQLITE_MISUSE */ "library routine called out of sequence", + /* SQLITE_MISUSE */ "bad parameter or other API misuse", +#ifdef SQLITE_DISABLE_LFS /* SQLITE_NOLFS */ "large file support is disabled", +#else + /* SQLITE_NOLFS */ 0, +#endif /* SQLITE_AUTH */ "authorization denied", - /* SQLITE_FORMAT */ "auxiliary database format error", - /* SQLITE_RANGE */ "bind or column index out of range", - /* SQLITE_NOTADB */ "file is encrypted or is not a database", + /* SQLITE_FORMAT */ 0, + /* SQLITE_RANGE */ "column index out of range", + /* SQLITE_NOTADB */ "file is not a database", }; const char *zErr = "unknown error"; switch( rc ){ @@ -142632,7 +144153,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ ** checkpointed. If an error is encountered it is returned immediately - ** no attempt is made to checkpoint any remaining databases. ** -** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. +** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART +** or TRUNCATE. */ SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){ int rc = SQLITE_OK; /* Return code */ @@ -142732,12 +144254,9 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){ 'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0 }; static const u16 misuse[] = { - 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ', - 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ', - 'c', 'a', 'l', 'l', 'e', 'd', ' ', - 'o', 'u', 't', ' ', - 'o', 'f', ' ', - 's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 0 + 'b', 'a', 'd', ' ', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', ' ', + 'o', 'r', ' ', 'o', 't', 'h', 'e', 'r', ' ', 'A', 'P', 'I', ' ', + 'm', 'i', 's', 'u', 's', 'e', 0 }; const void *z; @@ -143272,26 +144791,6 @@ static int openDatabase( if( rc ) return rc; #endif - /* Only allow sensible combinations of bits in the flags argument. - ** Throw an error if any non-sense combination is used. If we - ** do not block illegal combinations here, it could trigger - ** assert() statements in deeper layers. Sensible combinations - ** are: - ** - ** 1: SQLITE_OPEN_READONLY - ** 2: SQLITE_OPEN_READWRITE - ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE - */ - assert( SQLITE_OPEN_READONLY == 0x01 ); - assert( SQLITE_OPEN_READWRITE == 0x02 ); - assert( SQLITE_OPEN_CREATE == 0x04 ); - testcase( (1<<(flags&7))==0x02 ); /* READONLY */ - testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ - testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ - if( ((1<<(flags&7)) & 0x46)==0 ){ - return SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */ - } - if( sqlite3GlobalConfig.bCoreMutex==0 ){ isThreadsafe = 0; }else if( flags & SQLITE_OPEN_NOMUTEX ){ @@ -143383,6 +144882,9 @@ static int openDatabase( #if defined(SQLITE_ENABLE_FTS3_TOKENIZER) | SQLITE_Fts3Tokenizer #endif +#if defined(SQLITE_ENABLE_QPSG) + | SQLITE_EnableQPSG +#endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -143410,9 +144912,30 @@ static int openDatabase( db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0); assert( db->pDfltColl!=0 ); - /* Parse the filename/URI argument. */ + /* Parse the filename/URI argument + ** + ** Only allow sensible combinations of bits in the flags argument. + ** Throw an error if any non-sense combination is used. If we + ** do not block illegal combinations here, it could trigger + ** assert() statements in deeper layers. Sensible combinations + ** are: + ** + ** 1: SQLITE_OPEN_READONLY + ** 2: SQLITE_OPEN_READWRITE + ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE + */ db->openFlags = flags; - rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); + assert( SQLITE_OPEN_READONLY == 0x01 ); + assert( SQLITE_OPEN_READWRITE == 0x02 ); + assert( SQLITE_OPEN_CREATE == 0x04 ); + testcase( (1<<(flags&7))==0x02 ); /* READONLY */ + testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ + testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ + if( ((1<<(flags&7)) & 0x46)==0 ){ + rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */ + }else{ + rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); + } if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); @@ -143509,6 +145032,12 @@ static int openDatabase( } #endif +#ifdef SQLITE_ENABLE_DBPAGE_VTAB + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3DbpageRegister(db); + } +#endif + #ifdef SQLITE_ENABLE_DBSTAT_VTAB if( !db->mallocFailed && rc==SQLITE_OK){ rc = sqlite3DbstatRegister(db); @@ -143521,6 +145050,12 @@ static int openDatabase( } #endif +#ifdef SQLITE_ENABLE_STMTVTAB + if( !db->mallocFailed && rc==SQLITE_OK){ + rc = sqlite3StmtVtabInit(db); + } +#endif + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. @@ -143805,6 +145340,12 @@ SQLITE_PRIVATE int sqlite3CantopenError(int lineno){ return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); } #ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ + char zMsg[100]; + sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); + testcase( sqlite3GlobalConfig.xLog!=0 ); + return reportError(SQLITE_CORRUPT, lineno, zMsg); +} SQLITE_PRIVATE int sqlite3NomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); return reportError(SQLITE_NOMEM, lineno, "OOM"); @@ -144156,7 +145697,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** This action provides a run-time test to see how the ALWAYS and ** NEVER macros were defined at compile-time. ** - ** The return value is ALWAYS(X). + ** The return value is ALWAYS(X) if X is true, or 0 if X is false. ** ** The recommended test is X==2. If the return value is 2, that means ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the @@ -144179,7 +145720,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){ */ case SQLITE_TESTCTRL_ALWAYS: { int x = va_arg(ap,int); - rc = ALWAYS(x); + rc = x ? ALWAYS(x) : 0; break; } @@ -144246,22 +145787,6 @@ SQLITE_API int sqlite3_test_control(int op, ...){ } #endif - /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree); - ** - ** Pass pFree into sqlite3ScratchFree(). - ** If sz>0 then allocate a scratch buffer into pNew. - */ - case SQLITE_TESTCTRL_SCRATCHMALLOC: { - void *pFree, **ppNew; - int sz; - sz = va_arg(ap, int); - ppNew = va_arg(ap, void**); - pFree = va_arg(ap, void*); - if( sz ) *ppNew = sqlite3ScratchMalloc(sz); - sqlite3ScratchFree(pFree); - break; - } - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** ** If parameter onoff is non-zero, configure the wrappers so that all @@ -144403,7 +145928,7 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64( ){ const char *z = sqlite3_uri_parameter(zFilename, zParam); sqlite3_int64 v; - if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){ + if( z && sqlite3DecOrHexToI64(z, &v)==0 ){ bDflt = v; } return bDflt; @@ -144564,6 +146089,58 @@ SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){ } #endif /* SQLITE_ENABLE_SNAPSHOT */ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +/* +** Given the name of a compile-time option, return true if that option +** was used and false if not. +** +** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix +** is not required for a match. +*/ +SQLITE_API int sqlite3_compileoption_used(const char *zOptName){ + int i, n; + int nOpt; + const char **azCompileOpt; + +#if SQLITE_ENABLE_API_ARMOR + if( zOptName==0 ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + + azCompileOpt = sqlite3CompileOptions(&nOpt); + + if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7; + n = sqlite3Strlen30(zOptName); + + /* Since nOpt is normally in single digits, a linear search is + ** adequate. No need for a binary search. */ + for(i=0; i<nOpt; i++){ + if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0 + && sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0 + ){ + return 1; + } + } + return 0; +} + +/* +** Return the N-th compile-time option string. If N is out of range, +** return a NULL pointer. +*/ +SQLITE_API const char *sqlite3_compileoption_get(int N){ + int nOpt; + const char **azCompileOpt; + azCompileOpt = sqlite3CompileOptions(&nOpt); + if( N>=0 && N<nOpt ){ + return azCompileOpt[N]; + } + return 0; +} +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ + /************** End of main.c ************************************************/ /************** Begin file notify.c ******************************************/ /* @@ -147515,17 +149092,26 @@ static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){ } /* +** Free all resources currently held by the cursor passed as the only +** argument. +*/ +static void fts3ClearCursor(Fts3Cursor *pCsr){ + fts3CursorFinalizeStmt(pCsr); + sqlite3Fts3FreeDeferredTokens(pCsr); + sqlite3_free(pCsr->aDoclist); + sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); + sqlite3Fts3ExprFree(pCsr->pExpr); + memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); +} + +/* ** Close the cursor. For additional information see the documentation ** on the xClose method of the virtual table interface. */ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - fts3CursorFinalizeStmt(pCsr); - sqlite3Fts3ExprFree(pCsr->pExpr); - sqlite3Fts3FreeDeferredTokens(pCsr); - sqlite3_free(pCsr->aDoclist); - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); + fts3ClearCursor(pCsr); assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); sqlite3_free(pCsr); return SQLITE_OK; @@ -147551,7 +149137,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ }else{ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); if( !zSql ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); + rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0); sqlite3_free(zSql); } if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; @@ -149026,11 +150612,7 @@ static int fts3FilterMethod( assert( iIdx==nVal ); /* In case the cursor has been used before, clear it now. */ - fts3CursorFinalizeStmt(pCsr); - sqlite3_free(pCsr->aDoclist); - sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); - sqlite3Fts3ExprFree(pCsr->pExpr); - memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); + fts3ClearCursor(pCsr); /* Set the lower and upper bounds on docids to return */ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64); @@ -149088,7 +150670,7 @@ static int fts3FilterMethod( ); } if( zSql ){ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); + rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0); sqlite3_free(zSql); }else{ rc = SQLITE_NOMEM; @@ -149109,7 +150691,12 @@ static int fts3FilterMethod( ** routine to find out if it has reached the end of a result set. */ static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){ - return ((Fts3Cursor *)pCursor)->isEof; + Fts3Cursor *pCsr = (Fts3Cursor*)pCursor; + if( pCsr->isEof ){ + fts3ClearCursor(pCsr); + pCsr->isEof = 1; + } + return pCsr->isEof; } /* @@ -149150,8 +150737,7 @@ static int fts3ColumnMethod( switch( iCol-p->nColumn ){ case 0: /* The special 'table-name' column */ - sqlite3_result_blob(pCtx, &pCsr, sizeof(Fts3Cursor*), SQLITE_TRANSIENT); - sqlite3_result_subtype(pCtx, SQLITE_BLOB); + sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0); break; case 1: @@ -149369,9 +150955,10 @@ static int fts3FunctionArg( sqlite3_value *pVal, /* argv[0] passed to function */ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ ){ - int rc = SQLITE_OK; - if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){ - *ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal); + int rc; + *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor"); + if( (*ppCsr)!=0 ){ + rc = SQLITE_OK; }else{ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); sqlite3_result_error(pContext, zErr, -1); @@ -156295,7 +157882,8 @@ static int fts3SqlStmt( if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL); + rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + &pStmt, NULL); sqlite3_free(zSql); assert( rc==SQLITE_OK || pStmt==0 ); p->aStmt[eStmt] = pStmt; @@ -164383,14 +165971,6 @@ struct RtreeGeomCallback { void *pContext; }; - -/* -** Value for the first field of every RtreeMatchArg object. The MATCH -** operator tests that the first field of a blob operand matches this -** value to avoid operating on invalid blobs (which could cause a segfault). -*/ -#define RTREE_GEOMETRY_MAGIC 0x891245AB - /* ** An instance of this structure (in the form of a BLOB) is returned by ** the SQL functions that sqlite3_rtree_geometry_callback() and @@ -164398,7 +165978,7 @@ struct RtreeGeomCallback { ** operand to the MATCH operator of an R-Tree. */ struct RtreeMatchArg { - u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ + u32 iSize; /* Size of this object */ RtreeGeomCallback cb; /* Info about the callback functions */ int nParam; /* Number of parameters to the SQL function */ sqlite3_value **apSqlParam; /* Original SQL parameter values */ @@ -165693,33 +167273,17 @@ static int findLeafNode( ** operator. */ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ - RtreeMatchArg *pBlob; /* BLOB returned by geometry function */ + RtreeMatchArg *pBlob, *pSrc; /* BLOB returned by geometry function */ sqlite3_rtree_query_info *pInfo; /* Callback information */ - int nBlob; /* Size of the geometry function blob */ - int nExpected; /* Expected size of the BLOB */ - /* Check that value is actually a blob. */ - if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; - - /* Check that the blob is roughly the right size. */ - nBlob = sqlite3_value_bytes(pValue); - if( nBlob<(int)sizeof(RtreeMatchArg) ){ - return SQLITE_ERROR; - } - - pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob ); + pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg"); + if( pSrc==0 ) return SQLITE_ERROR; + pInfo = (sqlite3_rtree_query_info*) + sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize ); if( !pInfo ) return SQLITE_NOMEM; memset(pInfo, 0, sizeof(*pInfo)); pBlob = (RtreeMatchArg*)&pInfo[1]; - - memcpy(pBlob, sqlite3_value_blob(pValue), nBlob); - nExpected = (int)(sizeof(RtreeMatchArg) + - pBlob->nParam*sizeof(sqlite3_value*) + - (pBlob->nParam-1)*sizeof(RtreeDValue)); - if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){ - sqlite3_free(pInfo); - return SQLITE_ERROR; - } + memcpy(pBlob, pSrc, pSrc->iSize); pInfo->pContext = pBlob->cb.pContext; pInfo->nParam = pBlob->nParam; pInfo->aParam = pBlob->aParam; @@ -166921,7 +168485,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ int rc; /* Return code */ RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */ int iCell; /* Index of iDelete cell in pLeaf */ - RtreeNode *pRoot; /* Root node of rtree structure */ + RtreeNode *pRoot = 0; /* Root node of rtree structure */ /* Obtain a reference to the root node to initialize Rtree.iDepth */ @@ -167405,7 +168969,8 @@ static int rtreeSqlInit( for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){ char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix); if( zSql ){ - rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0); + rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, + appStmt[i], 0); }else{ rc = SQLITE_NOMEM; } @@ -167480,6 +169045,10 @@ static int getNodeSize( rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize); if( rc!=SQLITE_OK ){ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + }else if( pRtree->iNodeSize<(512-64) ){ + rc = SQLITE_CORRUPT_VTAB; + *pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"", + pRtree->zName); } } @@ -167752,7 +169321,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ sqlite3_result_error_nomem(ctx); }else{ int i; - pBlob->magic = RTREE_GEOMETRY_MAGIC; + pBlob->iSize = nBlob; pBlob->cb = pGeomCtx[0]; pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg]; pBlob->nParam = nArg; @@ -167769,7 +169338,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ sqlite3_result_error_nomem(ctx); rtreeMatchArgFree(pBlob); }else{ - sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree); + sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree); } } } @@ -167944,15 +169513,15 @@ static int icuLikeCompare( const uint8_t *zString, /* The UTF-8 string to compare against */ const UChar32 uEsc /* The escape character */ ){ - static const int MATCH_ONE = (UChar32)'_'; - static const int MATCH_ALL = (UChar32)'%'; + static const uint32_t MATCH_ONE = (uint32_t)'_'; + static const uint32_t MATCH_ALL = (uint32_t)'%'; int prevEscape = 0; /* True if the previous character was uEsc */ while( 1 ){ /* Read (and consume) the next character from the input pattern. */ - UChar32 uPattern; + uint32_t uPattern; SQLITE_ICU_READ_UTF8(zPattern, uPattern); if( uPattern==0 ) break; @@ -167994,16 +169563,16 @@ static int icuLikeCompare( if( *zString==0 ) return 0; SQLITE_ICU_SKIP_UTF8(zString); - }else if( !prevEscape && uPattern==uEsc){ + }else if( !prevEscape && uPattern==(uint32_t)uEsc){ /* Case 3. */ prevEscape = 1; }else{ /* Case 4. */ - UChar32 uString; + uint32_t uString; SQLITE_ICU_READ_UTF8(zString, uString); - uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); - uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); + uString = (uint32_t)u_foldCase((UChar32)uString, U_FOLD_CASE_DEFAULT); + uPattern = (uint32_t)u_foldCase((UChar32)uPattern, U_FOLD_CASE_DEFAULT); if( uString!=uPattern ){ return 0; } @@ -169100,6 +170669,28 @@ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum( ); /* +** Configure a limit for the amount of temp space that may be used by +** the RBU handle passed as the first argument. The new limit is specified +** in bytes by the second parameter. If it is positive, the limit is updated. +** If the second parameter to this function is passed zero, then the limit +** is removed entirely. If the second parameter is negative, the limit is +** not modified (this is useful for querying the current limit). +** +** In all cases the returned value is the current limit in bytes (zero +** indicates unlimited). +** +** If the temp space limit is exceeded during operation, an SQLITE_FULL +** error is returned. +*/ +SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64); + +/* +** Return the current amount of temp file space, in bytes, currently used by +** the RBU handle passed as the only argument. +*/ +SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*); + +/* ** Internally, each RBU connection uses a separate SQLite database ** connection to access the target and rbu update databases. This ** API allows the application direct access to these database handles. @@ -169167,10 +170758,10 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu); ** ** If an error has already occurred as part of an sqlite3rbu_step() ** or sqlite3rbu_open() call, or if one occurs within this function, an -** SQLite error code is returned. Additionally, *pzErrmsg may be set to -** point to a buffer containing a utf-8 formatted English language error -** message. It is the responsibility of the caller to eventually free any -** such buffer using sqlite3_free(). +** SQLite error code is returned. Additionally, if pzErrmsg is not NULL, +** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted +** English language error message. It is the responsibility of the caller to +** eventually free any such buffer using sqlite3_free(). ** ** Otherwise, if no error occurs, this function returns SQLITE_OK if the ** update has been partially applied, or SQLITE_DONE if it has been @@ -169225,7 +170816,7 @@ SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu); ** table exists but is not correctly populated, the value of the *pnOne ** output variable during stage 1 is undefined. */ -SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo); +SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo); /* ** Obtain an indication as to the current stage of an RBU update or vacuum. @@ -169335,6 +170926,13 @@ SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName); /* Maximum number of prepared UPDATE statements held by this module */ #define SQLITE_RBU_UPDATE_CACHESIZE 16 +/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM +** to enable checksum verification. +*/ +#ifndef RBU_ENABLE_DELTA_CKSUM +# define RBU_ENABLE_DELTA_CKSUM 0 +#endif + /* ** Swap two objects of type TYPE. */ @@ -169610,6 +171208,8 @@ struct sqlite3rbu { int pgsz; u8 *aBuf; i64 iWalCksum; + i64 szTemp; /* Current size of all temp files in use */ + i64 szTempLimit; /* Total size limit for temp files */ /* Used in RBU vacuum mode only */ int nRbu; /* Number of RBU VFS in the stack */ @@ -169618,23 +171218,33 @@ struct sqlite3rbu { /* ** An rbu VFS is implemented using an instance of this structure. +** +** Variable pRbu is only non-NULL for automatically created RBU VFS objects. +** It is NULL for RBU VFS objects created explicitly using +** sqlite3rbu_create_vfs(). It is used to track the total amount of temp +** space used by the RBU handle. */ struct rbu_vfs { sqlite3_vfs base; /* rbu VFS shim methods */ sqlite3_vfs *pRealVfs; /* Underlying VFS */ sqlite3_mutex *mutex; /* Mutex to protect pMain */ + sqlite3rbu *pRbu; /* Owner RBU object */ rbu_file *pMain; /* Linked list of main db files */ }; /* ** Each file opened by an rbu VFS is represented by an instance of ** the following structure. +** +** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable +** "sz" is set to the current size of the database file. */ struct rbu_file { sqlite3_file base; /* sqlite3_file methods */ sqlite3_file *pReal; /* Underlying file handle */ rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */ sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */ + i64 sz; /* Size of file in bytes (temp only) */ int openFlags; /* Flags this file was opened with */ u32 iCookie; /* Cookie value for main db files */ @@ -169697,6 +171307,7 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){ return v; } +#if RBU_ENABLE_DELTA_CKSUM /* ** Compute a 32-bit checksum on the N-byte buffer. Return the result. */ @@ -169731,6 +171342,7 @@ static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){ } return sum3; } +#endif /* ** Apply a delta. @@ -169761,7 +171373,7 @@ static int rbuDeltaApply( ){ unsigned int limit; unsigned int total = 0; -#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST +#if RBU_ENABLE_DELTA_CKSUM char *zOrigOut = zOut; #endif @@ -169816,7 +171428,7 @@ static int rbuDeltaApply( case ';': { zDelta++; lenDelta--; zOut[0] = 0; -#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST +#if RBU_ENABLE_DELTA_CKSUM if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){ /* ERROR: bad checksum */ return -1; @@ -172648,6 +174260,7 @@ static void rbuCreateVfs(sqlite3rbu *p){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd); assert( pVfs ); p->zVfsName = pVfs->zName; + ((rbu_vfs*)pVfs)->pRbu = p; } } @@ -173020,13 +174633,18 @@ SQLITE_API int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ /* Close the open database handle and VFS object. */ sqlite3_close(p->dbRbu); sqlite3_close(p->dbMain); + assert( p->szTemp==0 ); rbuDeleteVfs(p); sqlite3_free(p->aBuf); sqlite3_free(p->aFrame); rbuEditErrmsg(p); rc = p->rc; - *pzErrmsg = p->zErrmsg; + if( pzErrmsg ){ + *pzErrmsg = p->zErrmsg; + }else{ + sqlite3_free(p->zErrmsg); + } sqlite3_free(p->zState); sqlite3_free(p); }else{ @@ -173203,6 +174821,7 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){ */ static void rbuUnlockShm(rbu_file *p){ + assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); if( p->pRbu ){ int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock; int i; @@ -173216,6 +174835,18 @@ static void rbuUnlockShm(rbu_file *p){ } /* +*/ +static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){ + sqlite3rbu *pRbu = pFd->pRbu; + i64 nDiff = nNew - pFd->sz; + pRbu->szTemp += nDiff; + pFd->sz = nNew; + assert( pRbu->szTemp>=0 ); + if( pRbu->szTempLimit && pRbu->szTemp>pRbu->szTempLimit ) return SQLITE_FULL; + return SQLITE_OK; +} + +/* ** Close an rbu file. */ static int rbuVfsClose(sqlite3_file *pFile){ @@ -173240,6 +174871,9 @@ static int rbuVfsClose(sqlite3_file *pFile){ rbuUnlockShm(p); p->pReal->pMethods->xShmUnmap(p->pReal, 0); } + else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ + rbuUpdateTempSize(p, 0); + } /* Close the underlying file handle */ rc = p->pReal->pMethods->xClose(p->pReal); @@ -173357,11 +174991,19 @@ static int rbuVfsWrite( assert( p->openFlags & SQLITE_OPEN_MAIN_DB ); rc = rbuCaptureDbWrite(p->pRbu, iOfst); }else{ - if( pRbu && pRbu->eStage==RBU_STAGE_OAL - && (p->openFlags & SQLITE_OPEN_WAL) - && iOfst>=pRbu->iOalSz - ){ - pRbu->iOalSz = iAmt + iOfst; + if( pRbu ){ + if( pRbu->eStage==RBU_STAGE_OAL + && (p->openFlags & SQLITE_OPEN_WAL) + && iOfst>=pRbu->iOalSz + ){ + pRbu->iOalSz = iAmt + iOfst; + }else if( p->openFlags & SQLITE_OPEN_DELETEONCLOSE ){ + i64 szNew = iAmt+iOfst; + if( szNew>p->sz ){ + rc = rbuUpdateTempSize(p, szNew); + if( rc!=SQLITE_OK ) return rc; + } + } } rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){ @@ -173380,6 +175022,10 @@ static int rbuVfsWrite( */ static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ rbu_file *p = (rbu_file*)pFile; + if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ + int rc = rbuUpdateTempSize(p, size); + if( rc!=SQLITE_OK ) return rc; + } return p->pReal->pMethods->xTruncate(p->pReal, size); } @@ -173769,6 +175415,8 @@ static int rbuVfsOpen( pDb->pWalFd = pFd; } } + }else{ + pFd->pRbu = pRbuVfs->pRbu; } if( oflags & SQLITE_OPEN_MAIN_DB @@ -173845,7 +175493,9 @@ static int rbuVfsAccess( if( *pResOut ){ rc = SQLITE_CANTOPEN; }else{ - *pResOut = 1; + sqlite3_int64 sz = 0; + rc = rbuVfsFileSize(&pDb->base, &sz); + *pResOut = (sz>0); } } } @@ -174034,6 +175684,20 @@ SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent){ return rc; } +/* +** Configure the aggregate temp file size limit for this RBU handle. +*/ +SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu *pRbu, sqlite3_int64 n){ + if( n>=0 ){ + pRbu->szTempLimit = n; + } + return pRbu->szTempLimit; +} + +SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){ + return pRbu->szTemp; +} + /**************************************************************************/ @@ -174737,6 +176401,9 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } @@ -174745,6 +176412,338 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; } #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ /************** End of dbstat.c **********************************************/ +/************** Begin file dbpage.c ******************************************/ +/* +** 2017-10-11 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file contains an implementation of the "sqlite_dbpage" virtual table. +** +** The sqlite_dbpage virtual table is used to read or write whole raw +** pages of the database file. The pager interface is used so that +** uncommitted changes and changes recorded in the WAL file are correctly +** retrieved. +** +** Usage example: +** +** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123; +** +** This is an eponymous virtual table so it does not need to be created before +** use. The optional argument to the sqlite_dbpage() table name is the +** schema for the database file that is to be read. The default schema is +** "main". +** +** The data field of sqlite_dbpage table can be updated. The new +** value must be a BLOB which is the correct page size, otherwise the +** update fails. Rows may not be deleted or inserted. +*/ + +/* #include "sqliteInt.h" ** Requires access to internal data structures ** */ +#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ + && !defined(SQLITE_OMIT_VIRTUALTABLE) + +typedef struct DbpageTable DbpageTable; +typedef struct DbpageCursor DbpageCursor; + +struct DbpageCursor { + sqlite3_vtab_cursor base; /* Base class. Must be first */ + int pgno; /* Current page number */ + int mxPgno; /* Last page to visit on this scan */ +}; + +struct DbpageTable { + sqlite3_vtab base; /* Base class. Must be first */ + sqlite3 *db; /* The database */ + Pager *pPager; /* Pager being read/written */ + int iDb; /* Index of database to analyze */ + int szPage; /* Size of each page in bytes */ + int nPage; /* Number of pages in the file */ +}; + +/* +** Connect to or create a dbpagevfs virtual table. +*/ +static int dbpageConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + DbpageTable *pTab = 0; + int rc = SQLITE_OK; + int iDb; + + if( argc>=4 ){ + Token nm; + sqlite3TokenInit(&nm, (char*)argv[3]); + iDb = sqlite3FindDb(db, &nm); + if( iDb<0 ){ + *pzErr = sqlite3_mprintf("no such schema: %s", argv[3]); + return SQLITE_ERROR; + } + }else{ + iDb = 0; + } + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)"); + if( rc==SQLITE_OK ){ + pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable)); + if( pTab==0 ) rc = SQLITE_NOMEM_BKPT; + } + + assert( rc==SQLITE_OK || pTab==0 ); + if( rc==SQLITE_OK ){ + Btree *pBt = db->aDb[iDb].pBt; + memset(pTab, 0, sizeof(DbpageTable)); + pTab->db = db; + pTab->iDb = iDb; + pTab->pPager = pBt ? sqlite3BtreePager(pBt) : 0; + } + + *ppVtab = (sqlite3_vtab*)pTab; + return rc; +} + +/* +** Disconnect from or destroy a dbpagevfs virtual table. +*/ +static int dbpageDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** idxNum: +** +** 0 full table scan +** 1 pgno=?1 +*/ +static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ + int i; + pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ + for(i=0; i<pIdxInfo->nConstraint; i++){ + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; + if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + pIdxInfo->estimatedRows = 1; + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; + pIdxInfo->estimatedCost = 1.0; + pIdxInfo->idxNum = 1; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + break; + } + } + if( pIdxInfo->nOrderBy>=1 + && pIdxInfo->aOrderBy[0].iColumn<=0 + && pIdxInfo->aOrderBy[0].desc==0 + ){ + pIdxInfo->orderByConsumed = 1; + } + return SQLITE_OK; +} + +/* +** Open a new dbpagevfs cursor. +*/ +static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + DbpageCursor *pCsr; + + pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor)); + if( pCsr==0 ){ + return SQLITE_NOMEM_BKPT; + }else{ + memset(pCsr, 0, sizeof(DbpageCursor)); + pCsr->base.pVtab = pVTab; + pCsr->pgno = -1; + } + + *ppCursor = (sqlite3_vtab_cursor *)pCsr; + return SQLITE_OK; +} + +/* +** Close a dbpagevfs cursor. +*/ +static int dbpageClose(sqlite3_vtab_cursor *pCursor){ + DbpageCursor *pCsr = (DbpageCursor *)pCursor; + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* +** Move a dbpagevfs cursor to the next entry in the file. +*/ +static int dbpageNext(sqlite3_vtab_cursor *pCursor){ + int rc = SQLITE_OK; + DbpageCursor *pCsr = (DbpageCursor *)pCursor; + pCsr->pgno++; + return rc; +} + +static int dbpageEof(sqlite3_vtab_cursor *pCursor){ + DbpageCursor *pCsr = (DbpageCursor *)pCursor; + return pCsr->pgno > pCsr->mxPgno; +} + +static int dbpageFilter( + sqlite3_vtab_cursor *pCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + DbpageCursor *pCsr = (DbpageCursor *)pCursor; + DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; + int rc = SQLITE_OK; + Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; + + pTab->szPage = sqlite3BtreeGetPageSize(pBt); + pTab->nPage = sqlite3BtreeLastPage(pBt); + if( idxNum==1 ){ + pCsr->pgno = sqlite3_value_int(argv[0]); + if( pCsr->pgno<1 || pCsr->pgno>pTab->nPage ){ + pCsr->pgno = 1; + pCsr->mxPgno = 0; + }else{ + pCsr->mxPgno = pCsr->pgno; + } + }else{ + pCsr->pgno = 1; + pCsr->mxPgno = pTab->nPage; + } + return rc; +} + +static int dbpageColumn( + sqlite3_vtab_cursor *pCursor, + sqlite3_context *ctx, + int i +){ + DbpageCursor *pCsr = (DbpageCursor *)pCursor; + DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; + int rc = SQLITE_OK; + switch( i ){ + case 0: { /* pgno */ + sqlite3_result_int(ctx, pCsr->pgno); + break; + } + case 1: { /* data */ + DbPage *pDbPage = 0; + rc = sqlite3PagerGet(pTab->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); + if( rc==SQLITE_OK ){ + sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pTab->szPage, + SQLITE_TRANSIENT); + } + sqlite3PagerUnref(pDbPage); + break; + } + default: { /* schema */ + sqlite3 *db = sqlite3_context_db_handle(ctx); + sqlite3_result_text(ctx, db->aDb[pTab->iDb].zDbSName, -1, SQLITE_STATIC); + break; + } + } + return SQLITE_OK; +} + +static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + DbpageCursor *pCsr = (DbpageCursor *)pCursor; + *pRowid = pCsr->pgno; + return SQLITE_OK; +} + +static int dbpageUpdate( + sqlite3_vtab *pVtab, + int argc, + sqlite3_value **argv, + sqlite_int64 *pRowid +){ + DbpageTable *pTab = (DbpageTable *)pVtab; + int pgno; + DbPage *pDbPage = 0; + int rc = SQLITE_OK; + char *zErr = 0; + + if( argc==1 ){ + zErr = "cannot delete"; + goto update_fail; + } + pgno = sqlite3_value_int(argv[0]); + if( pgno<1 || pgno>pTab->nPage ){ + zErr = "bad page number"; + goto update_fail; + } + if( sqlite3_value_int(argv[1])!=pgno ){ + zErr = "cannot insert"; + goto update_fail; + } + if( sqlite3_value_type(argv[3])!=SQLITE_BLOB + || sqlite3_value_bytes(argv[3])!=pTab->szPage + ){ + zErr = "bad page value"; + goto update_fail; + } + rc = sqlite3PagerGet(pTab->pPager, pgno, (DbPage**)&pDbPage, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK ){ + memcpy(sqlite3PagerGetData(pDbPage), + sqlite3_value_blob(argv[3]), + pTab->szPage); + } + } + sqlite3PagerUnref(pDbPage); + return rc; + +update_fail: + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = sqlite3_mprintf("%s", zErr); + return SQLITE_ERROR; +} + +/* +** Invoke this routine to register the "dbpage" virtual table module +*/ +SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ + static sqlite3_module dbpage_module = { + 0, /* iVersion */ + dbpageConnect, /* xCreate */ + dbpageConnect, /* xConnect */ + dbpageBestIndex, /* xBestIndex */ + dbpageDisconnect, /* xDisconnect */ + dbpageDisconnect, /* xDestroy */ + dbpageOpen, /* xOpen - open a cursor */ + dbpageClose, /* xClose - close a cursor */ + dbpageFilter, /* xFilter - configure scan constraints */ + dbpageNext, /* xNext - advance a cursor */ + dbpageEof, /* xEof - check for end of scan */ + dbpageColumn, /* xColumn - read data */ + dbpageRowid, /* xRowid - read data */ + dbpageUpdate, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + }; + return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); +} +#elif defined(SQLITE_ENABLE_DBPAGE_VTAB) +SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } +#endif /* SQLITE_ENABLE_DBSTAT_VTAB */ + +/************** End of dbpage.c **********************************************/ /************** Begin file sqlite3session.c **********************************/ #if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK) @@ -177584,11 +179583,12 @@ static int sessionChangesetNext( p->in.iCurrent = p->in.iNext; op = p->in.aData[p->in.iNext++]; - if( op=='T' || op=='P' ){ + while( op=='T' || op=='P' ){ p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; p->in.iCurrent = p->in.iNext; + if( p->in.iNext>=p->in.nData ) return SQLITE_DONE; op = p->in.aData[p->in.iNext++]; } @@ -183334,7 +185334,8 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); ** fts5YY_MAX_SHIFT Maximum value for shift actions ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** fts5YY_MIN_REDUCE Maximum value for reduce actions +** fts5YY_MIN_REDUCE Minimum value for reduce actions +** fts5YY_MAX_REDUCE Maximum value for reduce actions ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op @@ -183446,12 +185447,12 @@ typedef union { *********** Begin parsing tables **********************************************/ #define fts5YY_ACTTAB_COUNT (98) static const fts5YYACTIONTYPE fts5yy_action[] = { - /* 0 */ 105, 19, 63, 6, 26, 66, 65, 24, 24, 17, - /* 10 */ 63, 6, 26, 16, 65, 54, 24, 18, 63, 6, - /* 20 */ 26, 10, 65, 12, 24, 75, 59, 63, 6, 26, - /* 30 */ 13, 65, 75, 24, 20, 63, 6, 26, 74, 65, - /* 40 */ 56, 24, 27, 63, 6, 26, 73, 65, 21, 24, - /* 50 */ 23, 15, 30, 11, 1, 64, 22, 25, 9, 65, + /* 0 */ 105, 19, 90, 6, 26, 93, 92, 24, 24, 17, + /* 10 */ 90, 6, 26, 16, 92, 54, 24, 18, 90, 6, + /* 20 */ 26, 10, 92, 12, 24, 75, 86, 90, 6, 26, + /* 30 */ 13, 92, 75, 24, 20, 90, 6, 26, 101, 92, + /* 40 */ 56, 24, 27, 90, 6, 26, 100, 92, 21, 24, + /* 50 */ 23, 15, 30, 11, 1, 91, 22, 25, 9, 92, /* 60 */ 7, 24, 3, 4, 5, 3, 4, 5, 3, 77, /* 70 */ 4, 5, 3, 61, 23, 15, 60, 11, 80, 12, /* 80 */ 2, 13, 68, 10, 29, 52, 55, 75, 31, 32, @@ -183556,6 +185557,7 @@ struct fts5yyParser { fts5yyStackEntry fts5yystk0; /* First stack entry */ #else fts5yyStackEntry fts5yystack[fts5YYSTACKDEPTH]; /* The parser's stack */ + fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ #endif }; typedef struct fts5yyParser fts5yyParser; @@ -183705,6 +185707,9 @@ static void sqlite3Fts5ParserInit(void *fts5yypParser){ pParser->fts5yytos = pParser->fts5yystack; pParser->fts5yystack[0].stateno = 0; pParser->fts5yystack[0].major = 0; +#if fts5YYSTACKDEPTH>0 + pParser->fts5yystackEnd = &pParser->fts5yystack[fts5YYSTACKDEPTH-1]; +#endif } #ifndef sqlite3Fts5Parser_ENGINEALWAYSONSTACK @@ -184003,7 +186008,7 @@ static void fts5yy_shift( } #endif #if fts5YYSTACKDEPTH>0 - if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5YYSTACKDEPTH] ){ + if( fts5yypParser->fts5yytos>fts5yypParser->fts5yystackEnd ){ fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; @@ -184031,35 +186036,35 @@ static void fts5yy_shift( ** is used during the reduce. */ static const struct { - fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - unsigned char nrhs; /* Number of right-hand side symbols in the rule */ + fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + signed char nrhs; /* Negative of the number of RHS symbols in the rule */ } fts5yyRuleInfo[] = { - { 16, 1 }, - { 20, 4 }, - { 20, 3 }, - { 20, 1 }, - { 20, 2 }, - { 21, 2 }, - { 21, 1 }, - { 17, 3 }, - { 17, 3 }, - { 17, 3 }, - { 17, 5 }, - { 17, 3 }, - { 17, 1 }, - { 19, 1 }, - { 19, 2 }, - { 18, 1 }, - { 18, 3 }, - { 22, 1 }, - { 22, 5 }, - { 23, 1 }, - { 23, 2 }, + { 16, -1 }, + { 20, -4 }, + { 20, -3 }, + { 20, -1 }, + { 20, -2 }, + { 21, -2 }, + { 21, -1 }, + { 17, -3 }, + { 17, -3 }, + { 17, -3 }, + { 17, -5 }, + { 17, -3 }, + { 17, -1 }, + { 19, -1 }, + { 19, -2 }, + { 18, -1 }, + { 18, -3 }, + { 22, -1 }, + { 22, -5 }, + { 23, -1 }, + { 23, -2 }, { 25, 0 }, - { 25, 2 }, - { 24, 4 }, - { 24, 2 }, - { 26, 1 }, + { 25, -2 }, + { 24, -4 }, + { 24, -2 }, + { 26, -1 }, { 26, 0 }, }; @@ -184083,7 +186088,7 @@ static void fts5yy_reduce( if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){ fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; fprintf(fts5yyTraceFILE, "%sReduce [%s], go to state %d.\n", fts5yyTracePrompt, - fts5yyRuleName[fts5yyruleno], fts5yymsp[-fts5yysize].stateno); + fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno); } #endif /* NDEBUG */ @@ -184098,7 +186103,7 @@ static void fts5yy_reduce( } #endif #if fts5YYSTACKDEPTH>0 - if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5YYSTACKDEPTH-1] ){ + if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){ fts5yyStackOverflow(fts5yypParser); return; } @@ -184265,20 +186270,24 @@ static void fts5yy_reduce( assert( fts5yyruleno<sizeof(fts5yyRuleInfo)/sizeof(fts5yyRuleInfo[0]) ); fts5yygoto = fts5yyRuleInfo[fts5yyruleno].lhs; fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs; - fts5yyact = fts5yy_find_reduce_action(fts5yymsp[-fts5yysize].stateno,(fts5YYCODETYPE)fts5yygoto); - if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){ - if( fts5yyact>fts5YY_MAX_SHIFT ){ - fts5yyact += fts5YY_MIN_REDUCE - fts5YY_MIN_SHIFTREDUCE; - } - fts5yymsp -= fts5yysize-1; + fts5yyact = fts5yy_find_reduce_action(fts5yymsp[fts5yysize].stateno,(fts5YYCODETYPE)fts5yygoto); + + /* There are no SHIFTREDUCE actions on nonterminals because the table + ** generator has simplified them to pure REDUCE actions. */ + assert( !(fts5yyact>fts5YY_MAX_SHIFT && fts5yyact<=fts5YY_MAX_SHIFTREDUCE) ); + + /* It is not possible for a REDUCE to be followed by an error */ + assert( fts5yyact!=fts5YY_ERROR_ACTION ); + + if( fts5yyact==fts5YY_ACCEPT_ACTION ){ + fts5yypParser->fts5yytos += fts5yysize; + fts5yy_accept(fts5yypParser); + }else{ + fts5yymsp += fts5yysize+1; fts5yypParser->fts5yytos = fts5yymsp; fts5yymsp->stateno = (fts5YYACTIONTYPE)fts5yyact; fts5yymsp->major = (fts5YYCODETYPE)fts5yygoto; fts5yyTraceShift(fts5yypParser, fts5yyact); - }else{ - assert( fts5yyact == fts5YY_ACCEPT_ACTION ); - fts5yypParser->fts5yytos -= fts5yysize; - fts5yy_accept(fts5yypParser); } } @@ -189575,10 +191584,11 @@ static int fts5HashResize(Fts5Hash *pHash){ for(i=0; i<pHash->nSlot; i++){ while( apOld[i] ){ - int iHash; + unsigned int iHash; Fts5HashEntry *p = apOld[i]; apOld[i] = p->pHashNext; - iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), strlen(fts5EntryKey(p))); + iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), + (int)strlen(fts5EntryKey(p))); p->pHashNext = apNew[iHash]; apNew[iHash] = p; } @@ -189881,7 +191891,7 @@ static int sqlite3Fts5HashQuery( int *pnDoclist /* OUT: Size of doclist in bytes */ ){ unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm); - char *zKey; + char *zKey = 0; Fts5HashEntry *p; for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ @@ -190669,7 +192679,8 @@ static int fts5IndexPrepareStmt( ){ if( p->rc==SQLITE_OK ){ if( zSql ){ - p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0); + p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, ppStmt, 0); }else{ p->rc = SQLITE_NOMEM; } @@ -190718,7 +192729,8 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){ if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0); + rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0); sqlite3_free(zSql); } if( rc!=SQLITE_OK ){ @@ -197317,7 +199329,8 @@ static int fts5PrepareStatement( if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0); + rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, &pRet, 0); if( rc!=SQLITE_OK ){ *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db)); } @@ -197453,7 +199466,8 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){ char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs); if( zSql ){ sqlite3_stmt *pStmt = 0; - rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0); + rc = sqlite3_prepare_v3(pConfig->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, &pStmt, 0); sqlite3_free(zSql); assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 ); if( rc==SQLITE_OK ){ @@ -199041,15 +201055,14 @@ static void fts5ModuleDestroy(void *pCtx){ static void fts5Fts5Func( sqlite3_context *pCtx, /* Function call context */ int nArg, /* Number of args */ - sqlite3_value **apUnused /* Function arguments */ + sqlite3_value **apArg /* Function arguments */ ){ Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); - char buf[8]; - UNUSED_PARAM2(nArg, apUnused); - assert( nArg==0 ); - assert( sizeof(buf)>=sizeof(pGlobal) ); - memcpy(buf, (void*)&pGlobal, sizeof(pGlobal)); - sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT); + fts5_api **ppApi; + UNUSED_PARAM(nArg); + assert( nArg==1 ); + ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr"); + if( ppApi ) *ppApi = &pGlobal->api; } /* @@ -199062,7 +201075,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2017-06-08 14:26:16 0ee482a1e0eae22e08edc8978c9733a96603d4509645f348ebf55b579e89636b", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ @@ -199114,7 +201127,7 @@ static int fts5Init(sqlite3 *db){ if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db); if( rc==SQLITE_OK ){ rc = sqlite3_create_function( - db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 + db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 ); } if( rc==SQLITE_OK ){ @@ -199316,7 +201329,8 @@ static int fts5StorageGetStmt( if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0); + rc = sqlite3_prepare_v3(pC->db, zSql, -1, + SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0); sqlite3_free(zSql); if( rc!=SQLITE_OK && pzErrMsg ){ *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); @@ -202289,6 +204303,11 @@ static int sqlite3Fts5GetVarintLen(u32 iVal){ ** the number of fts5 rows that contain at least one instance of term ** $term. Field $cnt is set to the total number of instances of term ** $term in the database. +** +** instance: +** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>)); +** +** One row for each term instance in the database. */ @@ -202304,7 +204323,7 @@ struct Fts5VocabTable { char *zFts5Db; /* Db containing fts5 table */ sqlite3 *db; /* Database handle */ Fts5Global *pGlobal; /* FTS5 global object for this database */ - int eType; /* FTS5_VOCAB_COL or ROW */ + int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */ }; struct Fts5VocabCursor { @@ -202324,16 +204343,22 @@ struct Fts5VocabCursor { i64 *aCnt; i64 *aDoc; - /* Output values used by 'row' and 'col' tables */ + /* Output values used by all tables. */ i64 rowid; /* This table's current rowid value */ Fts5Buffer term; /* Current value of 'term' column */ + + /* Output values Used by 'instance' tables only */ + i64 iInstPos; + int iInstOff; }; -#define FTS5_VOCAB_COL 0 -#define FTS5_VOCAB_ROW 1 +#define FTS5_VOCAB_COL 0 +#define FTS5_VOCAB_ROW 1 +#define FTS5_VOCAB_INSTANCE 2 #define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt" #define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt" +#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset" /* ** Bits for the mask used as the idxNum value by xBestIndex/xFilter. @@ -202361,6 +204386,9 @@ static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){ if( sqlite3_stricmp(zCopy, "row")==0 ){ *peType = FTS5_VOCAB_ROW; }else + if( sqlite3_stricmp(zCopy, "instance")==0 ){ + *peType = FTS5_VOCAB_INSTANCE; + }else { *pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy); rc = SQLITE_ERROR; @@ -202421,7 +204449,8 @@ static int fts5VocabInitVtab( ){ const char *azSchema[] = { "CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")", - "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")" + "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")", + "CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")" }; Fts5VocabTable *pRet = 0; @@ -202495,6 +204524,15 @@ static int fts5VocabCreateMethod( /* ** Implementation of the xBestIndex method. +** +** Only constraints of the form: +** +** term <= ? +** term == ? +** term >= ? +** +** are interpreted. Less-than and less-than-or-equal are treated +** identically, as are greater-than and greater-than-or-equal. */ static int fts5VocabBestIndexMethod( sqlite3_vtab *pUnused, @@ -202638,6 +204676,54 @@ static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){ return SQLITE_OK; } +static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){ + int rc = SQLITE_OK; + + if( sqlite3Fts5IterEof(pCsr->pIter) ){ + pCsr->bEof = 1; + }else{ + const char *zTerm; + int nTerm; + zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); + if( pCsr->nLeTerm>=0 ){ + int nCmp = MIN(nTerm, pCsr->nLeTerm); + int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); + if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){ + pCsr->bEof = 1; + } + } + + sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); + } + return rc; +} + +static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){ + int eDetail = pCsr->pConfig->eDetail; + int rc = SQLITE_OK; + Fts5IndexIter *pIter = pCsr->pIter; + i64 *pp = &pCsr->iInstPos; + int *po = &pCsr->iInstOff; + + while( eDetail==FTS5_DETAIL_NONE + || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) + ){ + pCsr->iInstPos = 0; + pCsr->iInstOff = 0; + + rc = sqlite3Fts5IterNextScan(pCsr->pIter); + if( rc==SQLITE_OK ){ + rc = fts5VocabInstanceNewTerm(pCsr); + if( eDetail==FTS5_DETAIL_NONE ) break; + } + if( rc ){ + pCsr->bEof = 1; + break; + } + } + + return rc; +} /* ** Advance the cursor to the next row in the table. @@ -202650,13 +204736,17 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ pCsr->rowid++; + if( pTab->eType==FTS5_VOCAB_INSTANCE ){ + return fts5VocabInstanceNext(pCsr); + } + if( pTab->eType==FTS5_VOCAB_COL ){ for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){ if( pCsr->aDoc[pCsr->iCol] ) break; } } - if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){ + if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){ if( sqlite3Fts5IterEof(pCsr->pIter) ){ pCsr->bEof = 1; }else{ @@ -202680,22 +204770,26 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); while( rc==SQLITE_OK ){ + int eDetail = pCsr->pConfig->eDetail; const u8 *pPos; int nPos; /* Position list */ i64 iPos = 0; /* 64-bit position read from poslist */ int iOff = 0; /* Current offset within position list */ pPos = pCsr->pIter->pData; nPos = pCsr->pIter->nData; - switch( pCsr->pConfig->eDetail ){ - case FTS5_DETAIL_FULL: - pPos = pCsr->pIter->pData; - nPos = pCsr->pIter->nData; - if( pTab->eType==FTS5_VOCAB_ROW ){ + + switch( pTab->eType ){ + case FTS5_VOCAB_ROW: + if( eDetail==FTS5_DETAIL_FULL ){ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ pCsr->aCnt[0]++; } - pCsr->aDoc[0]++; - }else{ + } + pCsr->aDoc[0]++; + break; + + case FTS5_VOCAB_COL: + if( eDetail==FTS5_DETAIL_FULL ){ int iCol = -1; while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ int ii = FTS5_POS2COLUMN(iPos); @@ -202709,13 +204803,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ iCol = ii; } } - } - break; - - case FTS5_DETAIL_COLUMNS: - if( pTab->eType==FTS5_VOCAB_ROW ){ - pCsr->aDoc[0]++; - }else{ + }else if( eDetail==FTS5_DETAIL_COLUMNS ){ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ assert_nc( iPos>=0 && iPos<nCol ); if( iPos>=nCol ){ @@ -202724,18 +204812,21 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ } pCsr->aDoc[iPos]++; } + }else{ + assert( eDetail==FTS5_DETAIL_NONE ); + pCsr->aDoc[0]++; } break; - default: - assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); - pCsr->aDoc[0]++; + default: + assert( pTab->eType==FTS5_VOCAB_INSTANCE ); break; } if( rc==SQLITE_OK ){ rc = sqlite3Fts5IterNextScan(pCsr->pIter); } + if( pTab->eType==FTS5_VOCAB_INSTANCE ) break; if( rc==SQLITE_OK ){ zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); @@ -202765,7 +204856,9 @@ static int fts5VocabFilterMethod( int nUnused, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ + Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + int eType = pTab->eType; int rc = SQLITE_OK; int iVal = 0; @@ -202805,11 +204898,16 @@ static int fts5VocabFilterMethod( } } - if( rc==SQLITE_OK ){ rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); } - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){ + rc = fts5VocabInstanceNewTerm(pCsr); + } + if( rc==SQLITE_OK + && !pCsr->bEof + && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE) + ){ rc = fts5VocabNextMethod(pCursor); } @@ -202851,13 +204949,41 @@ static int fts5VocabColumnMethod( }else{ iVal = pCsr->aCnt[pCsr->iCol]; } - }else{ + }else if( eType==FTS5_VOCAB_ROW ){ assert( iCol==1 || iCol==2 ); if( iCol==1 ){ iVal = pCsr->aDoc[0]; }else{ iVal = pCsr->aCnt[0]; } + }else{ + assert( eType==FTS5_VOCAB_INSTANCE ); + switch( iCol ){ + case 1: + sqlite3_result_int64(pCtx, pCsr->pIter->iRowid); + break; + case 2: { + int ii = -1; + if( eDetail==FTS5_DETAIL_FULL ){ + ii = FTS5_POS2COLUMN(pCsr->iInstPos); + }else if( eDetail==FTS5_DETAIL_COLUMNS ){ + ii = (int)pCsr->iInstPos; + } + if( ii>=0 && ii<pCsr->pConfig->nCol ){ + const char *z = pCsr->pConfig->azCol[ii]; + sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); + } + break; + } + default: { + assert( iCol==3 ); + if( eDetail==FTS5_DETAIL_FULL ){ + int ii = FTS5_POS2OFFSET(pCsr->iInstPos); + sqlite3_result_int(pCtx, ii); + } + break; + } + } } if( iVal>0 ) sqlite3_result_int64(pCtx, iVal); @@ -202916,3 +205042,311 @@ static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */ /************** End of fts5.c ************************************************/ +/************** Begin file stmt.c ********************************************/ +/* +** 2017-05-31 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file demonstrates an eponymous virtual table that returns information +** about all prepared statements for the database connection. +** +** Usage example: +** +** .load ./stmt +** .mode line +** .header on +** SELECT * FROM stmt; +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) +#if !defined(SQLITEINT_H) +/* #include "sqlite3ext.h" */ +#endif +SQLITE_EXTENSION_INIT1 +/* #include <assert.h> */ +/* #include <string.h> */ + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* stmt_vtab is a subclass of sqlite3_vtab which will +** serve as the underlying representation of a stmt virtual table +*/ +typedef struct stmt_vtab stmt_vtab; +struct stmt_vtab { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this stmt vtab */ +}; + +/* stmt_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result +*/ +typedef struct stmt_cursor stmt_cursor; +struct stmt_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this cursor */ + sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */ + sqlite3_int64 iRowid; /* The rowid */ +}; + +/* +** The stmtConnect() method is invoked to create a new +** stmt_vtab that describes the stmt virtual table. +** +** Think of this routine as the constructor for stmt_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the stmt_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against stmt will look like. +*/ +static int stmtConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + stmt_vtab *pNew; + int rc; + +/* Column numbers */ +#define STMT_COLUMN_SQL 0 /* SQL for the statement */ +#define STMT_COLUMN_NCOL 1 /* Number of result columns */ +#define STMT_COLUMN_RO 2 /* True if read-only */ +#define STMT_COLUMN_BUSY 3 /* True if currently busy */ +#define STMT_COLUMN_NSCAN 4 /* SQLITE_STMTSTATUS_FULLSCAN_STEP */ +#define STMT_COLUMN_NSORT 5 /* SQLITE_STMTSTATUS_SORT */ +#define STMT_COLUMN_NAIDX 6 /* SQLITE_STMTSTATUS_AUTOINDEX */ +#define STMT_COLUMN_NSTEP 7 /* SQLITE_STMTSTATUS_VM_STEP */ +#define STMT_COLUMN_REPREP 8 /* SQLITE_STMTSTATUS_REPREPARE */ +#define STMT_COLUMN_RUN 9 /* SQLITE_STMTSTATUS_RUN */ +#define STMT_COLUMN_MEM 10 /* SQLITE_STMTSTATUS_MEMUSED */ + + + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep," + "reprep,run,mem)"); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; +} + +/* +** This method is the destructor for stmt_cursor objects. +*/ +static int stmtDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** Constructor for a new stmt_cursor object. +*/ +static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + stmt_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->db = ((stmt_vtab*)p)->db; + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Destructor for a stmt_cursor. +*/ +static int stmtClose(sqlite3_vtab_cursor *cur){ + sqlite3_free(cur); + return SQLITE_OK; +} + + +/* +** Advance a stmt_cursor to its next row of output. +*/ +static int stmtNext(sqlite3_vtab_cursor *cur){ + stmt_cursor *pCur = (stmt_cursor*)cur; + pCur->iRowid++; + pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt); + return SQLITE_OK; +} + +/* +** Return values of columns for the row at which the stmt_cursor +** is currently pointing. +*/ +static int stmtColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + stmt_cursor *pCur = (stmt_cursor*)cur; + switch( i ){ + case STMT_COLUMN_SQL: { + sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT); + break; + } + case STMT_COLUMN_NCOL: { + sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt)); + break; + } + case STMT_COLUMN_RO: { + sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt)); + break; + } + case STMT_COLUMN_BUSY: { + sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt)); + break; + } + case STMT_COLUMN_MEM: { + i = SQLITE_STMTSTATUS_MEMUSED + + STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP; + /* Fall thru */ + } + case STMT_COLUMN_NSCAN: + case STMT_COLUMN_NSORT: + case STMT_COLUMN_NAIDX: + case STMT_COLUMN_NSTEP: + case STMT_COLUMN_REPREP: + case STMT_COLUMN_RUN: { + sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt, + i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0)); + break; + } + } + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + stmt_cursor *pCur = (stmt_cursor*)cur; + *pRowid = pCur->iRowid; + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int stmtEof(sqlite3_vtab_cursor *cur){ + stmt_cursor *pCur = (stmt_cursor*)cur; + return pCur->pStmt==0; +} + +/* +** This method is called to "rewind" the stmt_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to stmtColumn() or stmtRowid() or +** stmtEof(). +*/ +static int stmtFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + stmt_cursor *pCur = (stmt_cursor *)pVtabCursor; + pCur->pStmt = 0; + pCur->iRowid = 0; + return stmtNext(pVtabCursor); +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the stmt virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +*/ +static int stmtBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + pIdxInfo->estimatedCost = (double)500; + pIdxInfo->estimatedRows = 500; + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** stmt virtual table. +*/ +static sqlite3_module stmtModule = { + 0, /* iVersion */ + 0, /* xCreate */ + stmtConnect, /* xConnect */ + stmtBestIndex, /* xBestIndex */ + stmtDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + stmtOpen, /* xOpen - open a cursor */ + stmtClose, /* xClose - close a cursor */ + stmtFilter, /* xFilter - configure scan constraints */ + stmtNext, /* xNext - advance a cursor */ + stmtEof, /* xEof - check for end of scan */ + stmtColumn, /* xColumn - read data */ + stmtRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "sqlite_stmt", &stmtModule, 0); +#endif + return rc; +} + +#ifndef SQLITE_CORE +#ifdef _WIN32 +__declspec(dllexport) +#endif +SQLITE_API int sqlite3_stmt_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3StmtVtabInit(db); +#endif + return rc; +} +#endif /* SQLITE_CORE */ +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ + +/************** End of stmt.c ************************************************/ +#if __LINE__!=205346 +#undef SQLITE_SOURCE_ID +#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de4alt2" +#endif +/* Return the source-id for this library */ +SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } +/************************** End of sqlite3.c ******************************/ diff --git a/db/sqlite3/src/sqlite3.h b/db/sqlite3/src/sqlite3.h index 3deb9c79b..5f28e036b 100644 --- a/db/sqlite3/src/sqlite3.h +++ b/db/sqlite3/src/sqlite3.h @@ -1,5 +1,5 @@ /* -** 2001 September 15 +** 2001-09-15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -115,15 +115,17 @@ extern "C" { ** a string which identifies a particular check-in of SQLite ** within its configuration management system. ^The SQLITE_SOURCE_ID ** string contains the date and time of the check-in (UTC) and a SHA1 -** or SHA3-256 hash of the entire source tree. +** or SHA3-256 hash of the entire source tree. If the source code has +** been edited in any way since it was last checked in, then the last +** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.19.3" -#define SQLITE_VERSION_NUMBER 3019003 -#define SQLITE_SOURCE_ID "2017-06-08 14:26:16 0ee482a1e0eae22e08edc8978c9733a96603d4509645f348ebf55b579e89636b" +#define SQLITE_VERSION "3.21.0" +#define SQLITE_VERSION_NUMBER 3021000 +#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -139,7 +141,7 @@ extern "C" { ** ** <blockquote><pre> ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER ); -** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 ); +** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 ); ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 ); ** </pre></blockquote>)^ ** @@ -149,9 +151,11 @@ extern "C" { ** function is provided for use in DLLs since DLL users usually do not have ** direct access to string constants within the DLL. ^The ** sqlite3_libversion_number() function returns an integer equal to -** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns +** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns ** a pointer to a string constant whose value is the same as the -** [SQLITE_SOURCE_ID] C preprocessor macro. +** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built +** using an edited copy of [the amalgamation], then the last four characters +** of the hash might be different from [SQLITE_SOURCE_ID].)^ ** ** See also: [sqlite_version()] and [sqlite_source_id()]. */ @@ -417,7 +421,7 @@ SQLITE_API int sqlite3_exec( */ #define SQLITE_OK 0 /* Successful result */ /* beginning-of-error-codes */ -#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_ERROR 1 /* Generic error */ #define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ @@ -432,7 +436,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ -#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_EMPTY 16 /* Internal use only */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ #define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ @@ -440,7 +444,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ -#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_FORMAT 24 /* Not used */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ @@ -494,6 +498,9 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) #define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) #define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) +#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) +#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) +#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) @@ -580,6 +587,11 @@ SQLITE_API int sqlite3_exec( ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on ** read-only media and cannot be changed even by processes with ** elevated privileges. +** +** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying +** filesystem supports doing multiple write operations atomically when those +** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and +** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 @@ -595,6 +607,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_IMMUTABLE 0x00002000 +#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 /* ** CAPI3REF: File Locking Levels @@ -729,6 +742,7 @@ struct sqlite3_file { ** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] ** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE] ** <li> [SQLITE_IOCAP_IMMUTABLE] +** <li> [SQLITE_IOCAP_BATCH_ATOMIC] ** </ul> ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of @@ -1012,6 +1026,40 @@ struct sqlite3_io_methods { ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for ** this opcode. +** +** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]] +** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then +** the file descriptor is placed in "batch write mode", which +** means all subsequent write operations will be deferred and done +** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems +** that do not support batch atomic writes will return SQLITE_NOTFOUND. +** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to +** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or +** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make +** no VFS interface calls on the same [sqlite3_file] file descriptor +** except for calls to the xWrite method and the xFileControl method +** with [SQLITE_FCNTL_SIZE_HINT]. +** +** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]] +** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write +** operations since the previous successful call to +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically. +** This file control returns [SQLITE_OK] if and only if the writes were +** all performed successfully and have been committed to persistent storage. +** ^Regardless of whether or not it is successful, this file control takes +** the file descriptor out of batch write mode so that all subsequent +** write operations are independent. +** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]] +** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write +** operations since the previous successful call to +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. +** ^This file control takes the file descriptor out of batch write mode +** so that all subsequent write operations are independent. +** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1043,6 +1091,9 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_JOURNAL_POINTER 28 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 #define SQLITE_FCNTL_PDB 30 +#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 +#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 +#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -1613,6 +1664,16 @@ struct sqlite3_mem_methods { ** routines with a wrapper that simulations memory allocation failure or ** tracks memory usage, for example. </dd> ** +** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt> +** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of +** type int, interpreted as a boolean, which if true provides a hint to +** SQLite that it should avoid large memory allocations if possible. +** SQLite will run faster if it is free to make large memory allocations, +** but some application might prefer to run slower in exchange for +** guarantees about memory fragmentation that are possible if large +** allocations are avoided. This hint is normally off. +** </dd> +** ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt> ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, ** interpreted as a boolean, which enables or disables the collection of @@ -1630,25 +1691,7 @@ struct sqlite3_mem_methods { ** </dd> ** ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt> -** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer -** that SQLite can use for scratch memory. ^(There are three arguments -** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte -** aligned memory buffer from which the scratch allocations will be -** drawn, the size of each scratch allocation (sz), -** and the maximum number of scratch allocations (N).)^ -** The first argument must be a pointer to an 8-byte aligned buffer -** of at least sz*N bytes of memory. -** ^SQLite will not use more than one scratch buffers per thread. -** ^SQLite will never request a scratch buffer that is more than 6 -** times the database page size. -** ^If SQLite needs needs additional -** scratch memory beyond what is provided by this configuration option, then -** [sqlite3_malloc()] will be used to obtain the memory needed.<p> -** ^When the application provides any amount of scratch memory using -** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large -** [sqlite3_malloc|heap allocations]. -** This can help [Robson proof|prevent memory allocation failures] due to heap -** fragmentation in low-memory embedded systems. +** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used. ** </dd> ** ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt> @@ -1684,8 +1727,7 @@ struct sqlite3_mem_methods { ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt> ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer ** that SQLite will use for all of its dynamic memory allocation needs -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and -** [SQLITE_CONFIG_PAGECACHE]. +** beyond those provided for by [SQLITE_CONFIG_PAGECACHE]. ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns ** [SQLITE_ERROR] if invoked otherwise. @@ -1878,7 +1920,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ -#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */ #define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ #define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ #define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ @@ -1899,6 +1941,7 @@ struct sqlite3_mem_methods { #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ #define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ +#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ /* ** CAPI3REF: Database Connection Configuration Options @@ -2007,6 +2050,17 @@ struct sqlite3_mem_methods { ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** +** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> +** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates +** the [query planner stability guarantee] (QPSG). When the QPSG is active, +** a single SQL query statement will always use the same algorithm regardless +** of values of [bound parameters].)^ The QPSG disables some query optimizations +** that look at the values of bound parameters, which can make some queries +** slower. But the QPSG has the advantage of more predictable behavior. With +** the QPSG active, SQLite will always use the same query plan in the field as +** was used during testing in the lab. +** </dd> +** ** </dl> */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2016,6 +2070,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ /* @@ -2679,7 +2734,8 @@ SQLITE_API void sqlite3_randomness(int N, void *P); ** [database connection], supplied in the first argument. ** ^The authorizer callback is invoked as SQL statements are being compiled ** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], -** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various +** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()], +** and [sqlite3_prepare16_v3()]. ^At various ** points during the compilation process, as logic is being created ** to perform various actions, the authorizer callback is invoked to ** see if those actions are allowed. ^The authorizer callback should @@ -3086,10 +3142,10 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** ^If [URI filename] interpretation is enabled, and the filename argument ** begins with "file:", then the filename is interpreted as a URI. ^URI ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is -** set in the fourth argument to sqlite3_open_v2(), or if it has +** set in the third argument to sqlite3_open_v2(), or if it has ** been enabled globally using the [SQLITE_CONFIG_URI] option with the ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. -** As of SQLite version 3.7.7, URI filename interpretation is turned off +** URI filename interpretation is turned off ** by default, but future releases of SQLite might enable URI filename ** interpretation by default. See "[URI filenames]" for additional ** information. @@ -3468,6 +3524,29 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 +/* +** CAPI3REF: Prepare Flags +** +** These constants define various flags that can be passed into +** "prepFlags" parameter of the [sqlite3_prepare_v3()] and +** [sqlite3_prepare16_v3()] interfaces. +** +** New flags may be added in future releases of SQLite. +** +** <dl> +** [[SQLITE_PREPARE_PERSISTENT]] ^(<dt>SQLITE_PREPARE_PERSISTENT</dt> +** <dd>The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner +** that the prepared statement will be retained for a long time and +** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()] +** and [sqlite3_prepare16_v3()] assume that the prepared statement will +** be used just once or at most a few times and then destroyed using +** [sqlite3_finalize()] relatively soon. The current implementation acts +** on this hint by avoiding the use of [lookaside memory] so as not to +** deplete the limited store of lookaside memory. Future versions of +** SQLite may act on this hint differently. +** </dl> +*/ +#define SQLITE_PREPARE_PERSISTENT 0x01 /* ** CAPI3REF: Compiling An SQL Statement @@ -3475,17 +3554,29 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** METHOD: sqlite3 ** CONSTRUCTOR: sqlite3_stmt ** -** To execute an SQL query, it must first be compiled into a byte-code -** program using one of these routines. +** To execute an SQL statement, it must first be compiled into a byte-code +** program using one of these routines. Or, in other words, these routines +** are constructors for the [prepared statement] object. +** +** The preferred routine to use is [sqlite3_prepare_v2()]. The +** [sqlite3_prepare()] interface is legacy and should be avoided. +** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used +** for special purposes. +** +** The use of the UTF-8 interfaces is preferred, as SQLite currently +** does all parsing using UTF-8. The UTF-16 interfaces are provided +** as a convenience. The UTF-16 interfaces work by converting the +** input text into UTF-8, then invoking the corresponding UTF-8 interface. ** ** The first argument, "db", is a [database connection] obtained from a ** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or ** [sqlite3_open16()]. The database connection must not have been closed. ** ** The second argument, "zSql", is the statement to be compiled, encoded -** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() -** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() -** use UTF-16. +** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(), +** and sqlite3_prepare_v3() +** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(), +** and sqlite3_prepare16_v3() use UTF-16. ** ** ^If the nByte argument is negative, then zSql is read up to the ** first zero terminator. ^If nByte is positive, then it is the @@ -3512,10 +3603,11 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; ** otherwise an [error code] is returned. ** -** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are -** recommended for all new programs. The two older interfaces are retained -** for backwards compatibility, but their use is discouraged. -** ^In the "v2" interfaces, the prepared statement +** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(), +** and sqlite3_prepare16_v3() interfaces are recommended for all new programs. +** The older interfaces (sqlite3_prepare() and sqlite3_prepare16()) +** are retained for backwards compatibility, but their use is discouraged. +** ^In the "vX" interfaces, the prepared statement ** that is returned (the [sqlite3_stmt] object) contains a copy of the ** original SQL text. This causes the [sqlite3_step()] interface to ** behave differently in three ways: @@ -3548,6 +3640,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. ** </li> +** +** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having +** the extra prepFlags parameter, which is a bit array consisting of zero or +** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The +** sqlite3_prepare_v2() interface works exactly the same as +** sqlite3_prepare_v3() with a zero prepFlags parameter. ** </ol> */ SQLITE_API int sqlite3_prepare( @@ -3564,6 +3662,14 @@ SQLITE_API int sqlite3_prepare_v2( sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail /* OUT: Pointer to unused portion of zSql */ ); +SQLITE_API int sqlite3_prepare_v3( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); SQLITE_API int sqlite3_prepare16( sqlite3 *db, /* Database handle */ const void *zSql, /* SQL statement, UTF-16 encoded */ @@ -3578,6 +3684,14 @@ SQLITE_API int sqlite3_prepare16_v2( sqlite3_stmt **ppStmt, /* OUT: Statement handle */ const void **pzTail /* OUT: Pointer to unused portion of zSql */ ); +SQLITE_API int sqlite3_prepare16_v3( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); /* ** CAPI3REF: Retrieving Statement SQL @@ -3585,7 +3699,8 @@ SQLITE_API int sqlite3_prepare16_v2( ** ** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8 ** SQL text used to create [prepared statement] P if P was -** created by either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], +** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** string containing the SQL text of prepared statement P with ** [bound parameters] expanded. @@ -3704,8 +3819,9 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. -** Unprotected sqlite3_value objects may only be used with -** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** Unprotected sqlite3_value objects may only be used as arguments +** to [sqlite3_result_value()], [sqlite3_bind_value()], and +** [sqlite3_value_dup()]. ** The [sqlite3_value_blob | sqlite3_value_type()] family of ** interfaces require protected sqlite3_value objects. */ @@ -3811,6 +3927,15 @@ typedef struct sqlite3_context sqlite3_context; ** [sqlite3_blob_open | incremental BLOB I/O] routines. ** ^A negative value for the zeroblob results in a zero-length BLOB. ** +** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in +** [prepared statement] S to have an SQL value of NULL, but to also be +** associated with the pointer P of type T. ^D is either a NULL pointer or +** a pointer to a destructor function for P. ^SQLite will invoke the +** destructor D with a single argument of P when it is finished using +** P. The T parameter should be a static string, preferably a string +** literal. The sqlite3_bind_pointer() routine is part of the +** [pointer passing interface] added for SQLite 3.20.0. +** ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer ** for the [prepared statement] or with a prepared statement for which ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], @@ -3844,6 +3969,7 @@ SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*) SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*)); SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); @@ -3887,8 +4013,8 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); ** ^If the value N is out of range or if the N-th parameter is ** nameless, then NULL is returned. ^The returned string is ** always in UTF-8 encoding even if the named parameter was -** originally specified as UTF-16 in [sqlite3_prepare16()] or -** [sqlite3_prepare16_v2()]. +** originally specified as UTF-16 in [sqlite3_prepare16()], +** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and @@ -3905,7 +4031,8 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); ** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero ** is returned if no matching parameter is found. ^The parameter ** name must be given in UTF-8 even if the original statement -** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or +** [sqlite3_prepare16_v3()]. ** ** See also: [sqlite3_bind_blob|sqlite3_bind()], ** [sqlite3_bind_parameter_count()], and @@ -4059,16 +4186,18 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** CAPI3REF: Evaluate An SQL Statement ** METHOD: sqlite3_stmt ** -** After a [prepared statement] has been prepared using either -** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** After a [prepared statement] has been prepared using any of +** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()], +** or [sqlite3_prepare16_v3()] or one of the legacy ** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function ** must be called one or more times to evaluate the statement. ** ** The details of the behavior of the sqlite3_step() interface depend -** on whether the statement was prepared using the newer "v2" interface -** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy -** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the -** new "v2" interface is recommended for new applications but the legacy +** on whether the statement was prepared using the newer "vX" interfaces +** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()], +** [sqlite3_prepare16_v2()] or the older legacy +** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "vX" interface is recommended for new applications but the legacy ** interface will continue to be supported. ** ** ^In the legacy interface, the return value will be either [SQLITE_BUSY], @@ -4129,10 +4258,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** specific [error codes] that better describes the error. ** We admit that this is a goofy design. The problem has been fixed ** with the "v2" interface. If you prepare all of your SQL statements -** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()] +** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead ** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, ** then the more specific [error codes] are returned directly -** by sqlite3_step(). The use of the "v2" interface is recommended. +** by sqlite3_step(). The use of the "vX" interfaces is recommended. */ SQLITE_API int sqlite3_step(sqlite3_stmt*); @@ -4194,6 +4324,28 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** KEYWORDS: {column access functions} ** METHOD: sqlite3_stmt ** +** <b>Summary:</b> +** <blockquote><table border=0 cellpadding=0 cellspacing=0> +** <tr><td><b>sqlite3_column_blob</b><td>→<td>BLOB result +** <tr><td><b>sqlite3_column_double</b><td>→<td>REAL result +** <tr><td><b>sqlite3_column_int</b><td>→<td>32-bit INTEGER result +** <tr><td><b>sqlite3_column_int64</b><td>→<td>64-bit INTEGER result +** <tr><td><b>sqlite3_column_text</b><td>→<td>UTF-8 TEXT result +** <tr><td><b>sqlite3_column_text16</b><td>→<td>UTF-16 TEXT result +** <tr><td><b>sqlite3_column_value</b><td>→<td>The result as an +** [sqlite3_value|unprotected sqlite3_value] object. +** <tr><td> <td> <td> +** <tr><td><b>sqlite3_column_bytes</b><td>→<td>Size of a BLOB +** or a UTF-8 TEXT result in bytes +** <tr><td><b>sqlite3_column_bytes16 </b> +** <td>→ <td>Size of UTF-16 +** TEXT in bytes +** <tr><td><b>sqlite3_column_type</b><td>→<td>Default +** datatype of the result +** </table></blockquote> +** +** <b>Details:</b> +** ** ^These routines return information about a single column of the current ** result row of a query. ^In every case the first argument is a pointer ** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] @@ -4215,16 +4367,29 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** are called from a different thread while any of these routines ** are pending, then the results are undefined. ** +** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16) +** each return the value of a result column in a specific data format. If +** the result column is not initially in the requested format (for example, +** if the query returns an integer but the sqlite3_column_text() interface +** is used to extract the value) then an automatic type conversion is performed. +** ** ^The sqlite3_column_type() routine returns the ** [SQLITE_INTEGER | datatype code] for the initial data type ** of the result column. ^The returned value is one of [SQLITE_INTEGER], -** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value -** returned by sqlite3_column_type() is only meaningful if no type -** conversions have occurred as described below. After a type conversion, -** the value returned by sqlite3_column_type() is undefined. Future +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. +** The return value of sqlite3_column_type() can be used to decide which +** of the first six interface should be used to extract the column value. +** The value returned by sqlite3_column_type() is only meaningful if no +** automatic type conversions have occurred for the value in question. +** After a type conversion, the result of calling sqlite3_column_type() +** is undefined, though harmless. Future ** versions of SQLite may change the behavior of sqlite3_column_type() ** following a type conversion. ** +** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes() +** or sqlite3_column_bytes16() interfaces can be used to determine the size +** of that BLOB or string. +** ** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() ** routine returns the number of bytes in that BLOB or string. ** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts @@ -4261,9 +4426,13 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [sqlite3_column_value()] is used in any other way, including calls ** to routines like [sqlite3_value_int()], [sqlite3_value_text()], ** or [sqlite3_value_bytes()], the behavior is not threadsafe. +** Hence, the sqlite3_column_value() interface +** is normally only useful within the implementation of +** [application-defined SQL functions] or [virtual tables], not within +** top-level application code. ** -** These routines attempt to convert the value where appropriate. ^For -** example, if the internal representation is FLOAT and a text result +** The these routines may attempt to convert the datatype of the result. +** ^For example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to perform the ** conversion automatically. ^(The following table details the conversions ** that are applied: @@ -4335,7 +4504,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** ^The pointers returned are valid until a type conversion occurs as ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or ** [sqlite3_finalize()] is called. ^The memory space used to hold strings -** and BLOBs is freed automatically. Do <em>not</em> pass the pointers returned +** and BLOBs is freed automatically. Do not pass the pointers returned ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** [sqlite3_free()]. ** @@ -4346,15 +4515,15 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [SQLITE_NOMEM].)^ */ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); -SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object @@ -4588,21 +4757,40 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** CAPI3REF: Obtaining SQL Values ** METHOD: sqlite3_value ** -** The C-language implementation of SQL functions and aggregates uses -** this set of interface routines to access the parameter values on -** the function or aggregate. -** -** The xFunc (for scalar functions) or xStep (for aggregates) parameters -** to [sqlite3_create_function()] and [sqlite3_create_function16()] -** define callbacks that implement the SQL functions and aggregates. -** The 3rd parameter to these callbacks is an array of pointers to -** [protected sqlite3_value] objects. There is one [sqlite3_value] object for -** each parameter to the SQL function. These routines are used to -** extract values from the [sqlite3_value] objects. +** <b>Summary:</b> +** <blockquote><table border=0 cellpadding=0 cellspacing=0> +** <tr><td><b>sqlite3_value_blob</b><td>→<td>BLOB value +** <tr><td><b>sqlite3_value_double</b><td>→<td>REAL value +** <tr><td><b>sqlite3_value_int</b><td>→<td>32-bit INTEGER value +** <tr><td><b>sqlite3_value_int64</b><td>→<td>64-bit INTEGER value +** <tr><td><b>sqlite3_value_pointer</b><td>→<td>Pointer value +** <tr><td><b>sqlite3_value_text</b><td>→<td>UTF-8 TEXT value +** <tr><td><b>sqlite3_value_text16</b><td>→<td>UTF-16 TEXT value in +** the native byteorder +** <tr><td><b>sqlite3_value_text16be</b><td>→<td>UTF-16be TEXT value +** <tr><td><b>sqlite3_value_text16le</b><td>→<td>UTF-16le TEXT value +** <tr><td> <td> <td> +** <tr><td><b>sqlite3_value_bytes</b><td>→<td>Size of a BLOB +** or a UTF-8 TEXT in bytes +** <tr><td><b>sqlite3_value_bytes16 </b> +** <td>→ <td>Size of UTF-16 +** TEXT in bytes +** <tr><td><b>sqlite3_value_type</b><td>→<td>Default +** datatype of the value +** <tr><td><b>sqlite3_value_numeric_type </b> +** <td>→ <td>Best numeric datatype of the value +** </table></blockquote> +** +** <b>Details:</b> +** +** These routines extract type, size, and content information from +** [protected sqlite3_value] objects. Protected sqlite3_value objects +** are used to pass parameter information into implementation of +** [application-defined SQL functions] and [virtual tables]. ** ** These routines work only with [protected sqlite3_value] objects. ** Any attempt to use these routines on an [unprotected sqlite3_value] -** object results in undefined behavior. +** is not threadsafe. ** ** ^These routines work just like the corresponding [column access functions] ** except that these routines take a single [protected sqlite3_value] object @@ -4613,6 +4801,24 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces ** extract UTF-16 strings as big-endian and little-endian respectively. ** +** ^If [sqlite3_value] object V was initialized +** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)] +** and if X and Y are strings that compare equal according to strcmp(X,Y), +** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise, +** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer() +** routine is part of the [pointer passing interface] added for SQLite 3.20.0. +** +** ^(The sqlite3_value_type(V) interface returns the +** [SQLITE_INTEGER | datatype code] for the initial datatype of the +** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^ +** Other interfaces might change the datatype for an sqlite3_value object. +** For example, if the datatype is initially SQLITE_INTEGER and +** sqlite3_value_text(V) is called to extract a text value for that +** integer, then subsequent calls to sqlite3_value_type(V) might return +** SQLITE_TEXT. Whether or not a persistent internal datatype conversion +** occurs is undefined and may change from one release of SQLite to the next. +** ** ^(The sqlite3_value_numeric_type() interface attempts to apply ** numeric affinity to the value. This means that an attempt is ** made to convert the value to an integer or floating point. If @@ -4631,15 +4837,16 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** the SQL function that supplied the [sqlite3_value*] parameters. */ SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes(sqlite3_value*); -SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API double sqlite3_value_double(sqlite3_value*); SQLITE_API int sqlite3_value_int(sqlite3_value*); SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*); SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); @@ -4652,10 +4859,6 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. -** -** SQLite makes no use of subtype itself. It merely passes the subtype -** from the result of one [application-defined SQL function] into the -** input of another. */ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -4925,7 +5128,7 @@ typedef void (*sqlite3_destructor_type)(void*); ** when it has finished using that result. ** ^If the 4th parameter to the sqlite3_result_text* interfaces ** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT -** then SQLite makes a copy of the result into space obtained from +** then SQLite makes a copy of the result into space obtained ** from [sqlite3_malloc()] before it returns. ** ** ^The sqlite3_result_value() interface sets the result of @@ -4938,6 +5141,17 @@ typedef void (*sqlite3_destructor_type)(void*); ** [unprotected sqlite3_value] object is required, so either ** kind of [sqlite3_value] object can be used with this interface. ** +** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an +** SQL NULL value, just like [sqlite3_result_null(C)], except that it +** also associates the host-language pointer P or type T with that +** NULL value such that the pointer can be retrieved within an +** [application-defined SQL function] using [sqlite3_value_pointer()]. +** ^If the D parameter is not NULL, then it is a pointer to a destructor +** for the P parameter. ^SQLite invokes D with P as its only argument +** when SQLite is finished with P. The T parameter should be a static +** string and preferably a string literal. The sqlite3_result_pointer() +** routine is part of the [pointer passing interface] added for SQLite 3.20.0. +** ** If these routines are called from within the different thread ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. @@ -4961,6 +5175,7 @@ SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(* SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*)); SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); @@ -5620,7 +5835,9 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it -** does not. +** does not. If the table name parameter T in a call to +** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is +** undefined behavior. ** ** ^The column is identified by the second, third and fourth parameters to ** this function. ^(The second parameter is either the name of the database @@ -6030,15 +6247,20 @@ struct sqlite3_index_info { ** an operator that is part of a constraint term in the wHERE clause of ** a query that uses a [virtual table]. */ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_NE 68 +#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 +#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 +#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 +#define SQLITE_INDEX_CONSTRAINT_IS 72 /* ** CAPI3REF: Register A Virtual Table Implementation @@ -6790,7 +7012,7 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 -#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 @@ -6849,8 +7071,7 @@ SQLITE_API int sqlite3_status64( ** <dd>This parameter is the current amount of memory checked out ** using [sqlite3_malloc()], either directly or indirectly. The ** figure includes calls made to [sqlite3_malloc()] by the application -** and internal memory usage by the SQLite library. Scratch memory -** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** and internal memory usage by the SQLite library. Auxiliary page-cache ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in ** this parameter. The amount returned is the sum of the allocation ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^ @@ -6888,29 +7109,14 @@ SQLITE_API int sqlite3_status64( ** *pHighwater parameter to [sqlite3_status()] is of interest. ** The value written into the *pCurrent parameter is undefined.</dd>)^ ** -** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt> -** <dd>This parameter returns the number of allocations used out of the -** [scratch memory allocator] configured using -** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not -** in bytes. Since a single thread may only have one scratch allocation -** outstanding at time, this parameter also reports the number of threads -** using scratch memory at the same time.</dd>)^ +** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt> +** <dd>No longer used.</dd> ** ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt> -** <dd>This parameter returns the number of bytes of scratch memory -** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] -** buffer and where forced to overflow to [sqlite3_malloc()]. The values -** returned include overflows because the requested allocation was too -** larger (that is, because the requested allocation was larger than the -** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer -** slots were available. -** </dd>)^ -** -** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt> -** <dd>This parameter records the largest memory allocation request -** handed to [scratch memory allocator]. Only the value returned in the -** *pHighwater parameter to [sqlite3_status()] is of interest. -** The value written into the *pCurrent parameter is undefined.</dd>)^ +** <dd>No longer used.</dd> +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt> +** <dd>No longer used.</dd> ** ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt> ** <dd>The *pHighwater parameter records the deepest parser stack. @@ -6923,12 +7129,12 @@ SQLITE_API int sqlite3_status64( #define SQLITE_STATUS_MEMORY_USED 0 #define SQLITE_STATUS_PAGECACHE_USED 1 #define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 -#define SQLITE_STATUS_SCRATCH_USED 3 -#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ #define SQLITE_STATUS_MALLOC_SIZE 5 #define SQLITE_STATUS_PARSER_STACK 6 #define SQLITE_STATUS_PAGECACHE_SIZE 7 -#define SQLITE_STATUS_SCRATCH_SIZE 8 +#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ #define SQLITE_STATUS_MALLOC_COUNT 9 /* @@ -7133,6 +7339,24 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** used as a proxy for the total work done by the prepared statement. ** If the number of virtual machine operations exceeds 2147483647 ** then the value returned by this statement status code is undefined. +** +** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt> +** <dd>^This is the number of times that the prepare statement has been +** automatically regenerated due to schema changes or change to +** [bound parameters] that might affect the query plan. +** +** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> +** <dd>^This is the number of times that the prepared statement has +** been run. A single "run" for the purposes of this counter is one +** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. +** The counter is incremented on the first [sqlite3_step()] call of each +** cycle. +** +** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> +** <dd>^This is the approximate number of bytes of heap memory +** used to store the prepared statement. ^This value is not actually +** a counter, and so the resetFlg parameter to sqlite3_stmt_status() +** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ @@ -7140,6 +7364,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 +#define SQLITE_STMTSTATUS_REPREPARE 5 +#define SQLITE_STMTSTATUS_RUN 6 +#define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object @@ -9004,8 +9231,8 @@ SQLITE_API int sqlite3session_diff( */ SQLITE_API int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ - int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ - void **ppPatchset /* OUT: Buffer containing changeset */ + int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ + void **ppPatchset /* OUT: Buffer containing patchset */ ); /* @@ -9772,12 +9999,12 @@ SQLITE_API int sqlite3changeset_apply( ** ** <table border=1 style="margin-left:8ex;margin-right:8ex"> ** <tr><th>Streaming function<th>Non-streaming equivalent</th> -** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply] -** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat] -** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert] -** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start] -** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset] -** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset] +** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply] +** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat] +** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert] +** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start] +** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset] +** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset] ** </table> ** ** Non-streaming functions that accept changesets (or patchsets) as input diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 9d7f512f2..91f94adb8 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -227,10 +227,10 @@ gfxPlatformGtk::UpdateFontList() // out a more general list static const char kFontDejaVuSans[] = "DejaVu Sans"; static const char kFontDejaVuSerif[] = "DejaVu Serif"; -static const char kFontEmojiOneMozilla[] = "EmojiOne Mozilla"; static const char kFontFreeSans[] = "FreeSans"; static const char kFontFreeSerif[] = "FreeSerif"; static const char kFontTakaoPGothic[] = "TakaoPGothic"; +static const char kFontTwemojiMozilla[] = "Twemoji Mozilla"; static const char kFontDroidSansFallback[] = "Droid Sans Fallback"; static const char kFontWenQuanYiMicroHei[] = "WenQuanYi Micro Hei"; static const char kFontNanumGothic[] = "NanumGothic"; @@ -254,7 +254,7 @@ gfxPlatformGtk::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh, uint32_t p = aCh >> 16; if (p == 1) { // try color emoji font, unless VS15 (text style) present if (aNextCh != 0xfe0fu && aNextCh != 0xfe0eu) { - aFontList.AppendElement(kFontEmojiOneMozilla); + aFontList.AppendElement(kFontTwemojiMozilla); } } } diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 84199170b..af4d932a9 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -634,7 +634,6 @@ static const char kFontCambriaMath[] = "Cambria Math"; static const char kFontEbrima[] = "Ebrima"; static const char kFontEstrangeloEdessa[] = "Estrangelo Edessa"; static const char kFontEuphemia[] = "Euphemia"; -static const char kFontEmojiOneMozilla[] = "EmojiOne Mozilla"; static const char kFontGabriola[] = "Gabriola"; static const char kFontJavaneseText[] = "Javanese Text"; static const char kFontKhmerUI[] = "Khmer UI"; @@ -661,6 +660,7 @@ static const char kFontSegoeUIEmoji[] = "Segoe UI Emoji"; static const char kFontSegoeUISymbol[] = "Segoe UI Symbol"; static const char kFontSylfaen[] = "Sylfaen"; static const char kFontTraditionalArabic[] = "Traditional Arabic"; +static const char kFontTwemojiMozilla[] = "Twemoji Mozilla"; static const char kFontUtsaah[] = "Utsaah"; static const char kFontYuGothic[] = "Yu Gothic"; @@ -671,7 +671,7 @@ gfxWindowsPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh, { if (aNextCh == 0xfe0fu) { aFontList.AppendElement(kFontSegoeUIEmoji); - aFontList.AppendElement(kFontEmojiOneMozilla); + aFontList.AppendElement(kFontTwemojiMozilla); } // Arial is used as the default fallback for system fallback @@ -683,11 +683,11 @@ gfxWindowsPlatform::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh, if (aNextCh == 0xfe0eu) { aFontList.AppendElement(kFontSegoeUISymbol); aFontList.AppendElement(kFontSegoeUIEmoji); - aFontList.AppendElement(kFontEmojiOneMozilla); + aFontList.AppendElement(kFontTwemojiMozilla); } else { if (aNextCh != 0xfe0fu) { aFontList.AppendElement(kFontSegoeUIEmoji); - aFontList.AppendElement(kFontEmojiOneMozilla); + aFontList.AppendElement(kFontTwemojiMozilla); } aFontList.AppendElement(kFontSegoeUISymbol); } diff --git a/old-configure.in b/old-configure.in index 9eb213988..c7d882e2d 100644 --- a/old-configure.in +++ b/old-configure.in @@ -68,7 +68,7 @@ GNOMEUI_VERSION=2.2.0 GCONF_VERSION=1.2.1 STARTUP_NOTIFICATION_VERSION=0.8 DBUS_VERSION=0.60 -SQLITE_VERSION=3.19.3 +SQLITE_VERSION=3.21.0 dnl Set various checks dnl ======================================================== diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index ae71d0868..f654db769 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -536,10 +536,6 @@ class Build(MachCommandBase): # arguably make the build action useful for Fennec. Another day... if self.substs['MOZ_BUILD_APP'] != 'mobile/android': print('To take your build for a test drive, run: |mach run|') - app = self.substs['MOZ_BUILD_APP'] - if app in ('browser', 'mobile/android'): - print('For more information on what to do now, see ' - 'https://developer.mozilla.org/docs/Developer_Guide/So_You_Just_Built_Firefox') except Exception: # Ignore Exceptions in case we can't find config.status (such # as when doing OSX Universal builds) diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 99ee42fde..45889a191 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -87,7 +87,7 @@ <li><a href="about:license#dtoa">dtoa License</a></li> <li><a href="about:license#hunspell-nl">Dutch Spellchecking Dictionary License</a></li> #if defined(XP_WIN) || defined(XP_LINUX) - <li><a href="about:license#emojione">EmojiOne License</a></li> + <li><a href="about:license#twemoji">Twemoji License</a></li> #endif <li><a href="about:license#hunspell-ee">Estonian Spellchecking Dictionary License</a></li> <li><a href="about:license#expat">Expat License</a></li> @@ -2911,14 +2911,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <hr> #if defined(XP_WIN) || defined(XP_LINUX) - <h1><a id="emojione"></a>EmojiOne License</h1> + <h1><a id="twemoji"></a>Twemoji License</h1> <p>This license applies to the emoji art contained within the bundled emoji font file.</p> <pre> -Copyright (c) 2016 Ranks.com Inc. -Copyright (c) 2014 Twitter, Inc and other contributors. +Copyright (c) 2018 Twitter, Inc and other contributors. Creative Commons Attribution 4.0 International (CC BY 4.0) |