From 62d2cd473b65edb676754ec1da1a7f94cfe0a693 Mon Sep 17 00:00:00 2001 From: tannal Date: Tue, 3 Mar 2026 07:14:47 +0800 Subject: [PATCH 001/106] cli: add --max-heap-size option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/58708 Reviewed-By: Gürgün Dayıoğlu --- doc/api/cli.md | 7 ++++ src/node_options.cc | 1 + test/common/v8-max-heap-size-option.js | 49 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 test/common/v8-max-heap-size-option.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 7c50ecc68774d8..79d0de607d3e1c 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -3741,6 +3741,7 @@ V8 options that are allowed are: * `--expose-gc` * `--interpreted-frames-native-stack` * `--jitless` +* `--max-heap-size` * `--max-old-space-size` * `--max-semi-space-size` * `--perf-basic-prof-only-functions` @@ -4099,6 +4100,12 @@ documented here: ### `--jitless` +### `--max-heap-size` + +Specifies the maximum heap size (in megabytes) for the process. + +This option is typically used to limit the amount of memory the process can use for its JavaScript heap. + diff --git a/src/node_options.cc b/src/node_options.cc index 60c08b95c2c798..3e83ac913eb1c7 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -1228,6 +1228,7 @@ PerIsolateOptionsParser::PerIsolateOptionsParser( "help system profilers to translate JavaScript interpreted frames", V8Option{}, kAllowedInEnvvar); + AddOption("--max-heap-size", "", V8Option{}, kAllowedInEnvvar); AddOption("--max-old-space-size", "", V8Option{}, kAllowedInEnvvar); AddOption("--max-old-space-size-percentage", "set V8's max old space size as a percentage of available memory " diff --git a/test/common/v8-max-heap-size-option.js b/test/common/v8-max-heap-size-option.js new file mode 100644 index 00000000000000..4487b011a97cdf --- /dev/null +++ b/test/common/v8-max-heap-size-option.js @@ -0,0 +1,49 @@ +'use strict'; + +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const path = require('path'); +const fs = require('fs'); +const tmpdir = require('./tmpdir'); + +const testScript = ` + const v8 = require('v8'); + const stats = v8.getHeapStatistics(); + const maxHeapSizeMB = Math.round(stats.heap_size_limit / 1024 / 1024); + console.log(maxHeapSizeMB); +`; + +tmpdir.refresh(); +const scriptPath = path.join(tmpdir.path, 'heap-limit-test.js'); +fs.writeFileSync(scriptPath, testScript); + +const child = spawnSync( + process.execPath, + [scriptPath], + { + encoding: 'utf8', + env: { + ...process.env, + NODE_OPTIONS: '--max-heap-size=750', + }, + }, +); + +assert.strictEqual( + child.status, + 0, + [ + `Child process did not exit cleanly.`, + ` Exit code: ${child.status}`, + child.stderr ? ` Stderr: ${child.stderr.toString()}` : '', + child.stdout ? ` Stdout: ${child.stdout.toString()}` : '', + ].filter(Boolean).join('\n'), +); +const output = child.stdout.trim(); +const heapLimit = Number(output); + +assert.strictEqual( + heapLimit, + 750, + `max heap size is ${heapLimit}MB, expected 750MB`, +); From 67b854d4071cca13c582b90251ca1765e26dbdef Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 6 Mar 2026 16:38:36 +0100 Subject: [PATCH 002/106] repl: remove dependency on domain module Replace the domain-based error handling with AsyncLocalStorage and setUncaughtExceptionCaptureCallback. This removes the REPL's dependency on the deprecated domain module while preserving all existing behavior: - Synchronous errors during eval are caught and displayed - Async errors (setTimeout, promises, etc.) are caught via the uncaught exception capture callback - Top-level await errors are caught and displayed - The REPL continues operating after errors - Multiple REPL instances can coexist with errors routed correctly Changes: - Use AsyncLocalStorage to track which REPL instance owns an async context, replacing domain's automatic async tracking - Add setupExceptionCapture() to install setUncaughtExceptionCaptureCallback for catching async errors and routing them to the correct REPL - Extract error handling logic into REPLServer.prototype._handleError() - Wrap eval execution in replContext.run() for async context tracking - Update newListener protection to check AsyncLocalStorage context - Throw ERR_INVALID_ARG_VALUE if options.domain is passed PR-URL: https://github.com/nodejs/node/pull/61227 Reviewed-By: Yagiz Nizipli Reviewed-By: Marco Ippolito Reviewed-By: Rafael Gonzaga --- doc/api/process.md | 48 ++- lib/domain.js | 20 +- lib/internal/bootstrap/node.js | 3 + lib/internal/process/execution.js | 61 +++- lib/repl.js | 326 ++++++++++-------- test/common/repl.js | 8 +- .../repl-tab-completion-nested-repls.js | 8 +- ...ad-after-set-uncaught-exception-capture.js | 25 +- ...t-uncaught-exception-capture-after-load.js | 37 +- .../test-repl-eval-error-after-close.js | 2 - test/parallel/test-repl-let-process.js | 2 +- test/parallel/test-repl-mode.js | 4 +- ...est-repl-multiple-instances-async-error.js | 69 ++++ .../parallel/test-repl-pretty-custom-stack.js | 2 - .../test-repl-pretty-stack-custom-writer.js | 5 +- test/parallel/test-repl-pretty-stack.js | 13 +- test/parallel/test-repl-preview-newlines.js | 4 +- test/parallel/test-repl-syntax-error-stack.js | 2 +- test/parallel/test-repl-tab-complete-crash.js | 2 +- test/parallel/test-repl-tab.js | 2 - test/parallel/test-repl-top-level-await.js | 2 +- .../test-repl-uncaught-exception-async.js | 17 +- ...st-repl-uncaught-exception-evalcallback.js | 25 +- test/parallel/test-repl-uncaught-exception.js | 15 +- test/parallel/test-repl-underscore.js | 2 - test/pummel/test-repl-paste-big-data.js | 2 +- 26 files changed, 417 insertions(+), 289 deletions(-) create mode 100644 test/parallel/test-repl-multiple-instances-async-error.js diff --git a/doc/api/process.md b/doc/api/process.md index 20488287920a95..a893d11d619b0c 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -736,6 +736,44 @@ generate a core file. This feature is not available in [`Worker`][] threads. +## `process.addUncaughtExceptionCaptureCallback(fn)` + + + +> Stability: 1 - Experimental + +* `fn` {Function} + +The `process.addUncaughtExceptionCaptureCallback()` function adds a callback +that will be invoked when an uncaught exception occurs, receiving the exception +value as its first argument. + +Unlike [`process.setUncaughtExceptionCaptureCallback()`][], this function allows +multiple callbacks to be registered and does not conflict with the +[`domain`][] module. Callbacks are called in reverse order of registration +(most recent first). If a callback returns `true`, subsequent callbacks +and the default uncaught exception handling are skipped. + +```mjs +import process from 'node:process'; + +process.addUncaughtExceptionCaptureCallback((err) => { + console.error('Caught exception:', err.message); + return true; // Indicates exception was handled +}); +``` + +```cjs +const process = require('node:process'); + +process.addUncaughtExceptionCaptureCallback((err) => { + console.error('Caught exception:', err.message); + return true; // Indicates exception was handled +}); +``` + ## `process.allowedNodeEnvironmentFlags` * `fn` {Function|null} @@ -4034,8 +4077,8 @@ To unset the capture function, method with a non-`null` argument while another capture function is set will throw an error. -Using this function is mutually exclusive with using the deprecated -[`domain`][] built-in module. +To register multiple callbacks that can coexist, use +[`process.addUncaughtExceptionCaptureCallback()`][] instead. ## `process.sourceMapsEnabled` @@ -4567,6 +4610,7 @@ cases: [`net.Socket`]: net.md#class-netsocket [`os.constants.dlopen`]: os.md#dlopen-constants [`postMessageToThread()`]: worker_threads.md#worker_threadspostmessagetothreadthreadid-value-transferlist-timeout +[`process.addUncaughtExceptionCaptureCallback()`]: #processadduncaughtexceptioncapturecallbackfn [`process.argv`]: #processargv [`process.config`]: #processconfig [`process.execPath`]: #processexecpath diff --git a/lib/domain.js b/lib/domain.js index 7dd16ee1bf59ef..f3a42271d2326d 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -40,14 +40,11 @@ const { ReflectApply, SafeMap, SafeWeakMap, - StringPrototypeRepeat, Symbol, } = primordials; const EventEmitter = require('events'); const { - ERR_DOMAIN_CALLBACK_NOT_AVAILABLE, - ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE, ERR_UNHANDLED_ERROR, } = require('internal/errors').codes; const { createHook } = require('async_hooks'); @@ -119,22 +116,9 @@ const asyncHook = createHook({ }, }); -// When domains are in use, they claim full ownership of the -// uncaught exception capture callback. -if (process.hasUncaughtExceptionCaptureCallback()) { - throw new ERR_DOMAIN_CALLBACK_NOT_AVAILABLE(); -} - -// Get the stack trace at the point where `domain` was required. -// eslint-disable-next-line no-restricted-syntax -const domainRequireStack = new Error('require(`domain`) at this point').stack; - +// Domain uses the stacking capability of setUncaughtExceptionCaptureCallback +// to coexist with other callbacks (e.g., REPL). const { setUncaughtExceptionCaptureCallback } = process; -process.setUncaughtExceptionCaptureCallback = function(fn) { - const err = new ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE(); - err.stack += `\n${StringPrototypeRepeat('-', 40)}\n${domainRequireStack}`; - throw err; -}; let sendMakeCallbackDeprecation = false; diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 2fafdb92a78e04..af4027b7324c7b 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -307,6 +307,7 @@ ObjectDefineProperty(process, 'features', { const { onGlobalUncaughtException, setUncaughtExceptionCaptureCallback, + addUncaughtExceptionCaptureCallback, hasUncaughtExceptionCaptureCallback, } = require('internal/process/execution'); @@ -319,6 +320,8 @@ ObjectDefineProperty(process, 'features', { process._fatalException = onGlobalUncaughtException; process.setUncaughtExceptionCaptureCallback = setUncaughtExceptionCaptureCallback; + process.addUncaughtExceptionCaptureCallback = + addUncaughtExceptionCaptureCallback; process.hasUncaughtExceptionCaptureCallback = hasUncaughtExceptionCaptureCallback; } diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index 9f484e6a611d33..4a2b57790bd7e6 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -1,6 +1,7 @@ 'use strict'; const { + ArrayPrototypePush, RegExpPrototypeExec, StringPrototypeIndexOf, StringPrototypeSlice, @@ -17,6 +18,7 @@ const { ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET, }, } = require('internal/errors'); +const { validateFunction } = require('internal/validators'); const { pathToFileURL } = require('internal/url'); const { exitCodes: { kGenericUserError } } = internalBinding('errors'); const { @@ -105,15 +107,18 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { } const exceptionHandlerState = { - captureFn: null, + captureFn: null, // Primary callback (for domain's exclusive use) + auxiliaryCallbacks: [], // Auxiliary callbacks (for REPL, etc.) - always called reportFlag: false, }; function setUncaughtExceptionCaptureCallback(fn) { if (fn === null) { exceptionHandlerState.captureFn = fn; - shouldAbortOnUncaughtToggle[0] = 1; - process.report.reportOnUncaughtException = exceptionHandlerState.reportFlag; + if (exceptionHandlerState.auxiliaryCallbacks.length === 0) { + shouldAbortOnUncaughtToggle[0] = 1; + process.report.reportOnUncaughtException = exceptionHandlerState.reportFlag; + } return; } if (typeof fn !== 'function') { @@ -129,6 +134,21 @@ function setUncaughtExceptionCaptureCallback(fn) { process.report.reportOnUncaughtException = false; } +// Add an auxiliary callback that coexists with the primary callback. +// Auxiliary callbacks are called first; if any returns true, the error is handled. +// Otherwise, the primary callback (if set) is called. +function addUncaughtExceptionCaptureCallback(fn) { + validateFunction(fn, 'fn'); + if (exceptionHandlerState.auxiliaryCallbacks.length === 0 && + exceptionHandlerState.captureFn === null) { + exceptionHandlerState.reportFlag = + process.report.reportOnUncaughtException === true; + process.report.reportOnUncaughtException = false; + shouldAbortOnUncaughtToggle[0] = 0; + } + ArrayPrototypePush(exceptionHandlerState.auxiliaryCallbacks, fn); +} + function hasUncaughtExceptionCaptureCallback() { return exceptionHandlerState.captureFn !== null; } @@ -154,21 +174,33 @@ function createOnGlobalUncaughtException() { const type = fromPromise ? 'unhandledRejection' : 'uncaughtException'; process.emit('uncaughtExceptionMonitor', er, type); + // Primary callback (e.g., domain) has priority and always handles the exception if (exceptionHandlerState.captureFn !== null) { exceptionHandlerState.captureFn(er); - } else if (!process.emit('uncaughtException', er, type)) { - // If someone handled it, then great. Otherwise, die in C++ land - // since that means that we'll exit the process, emit the 'exit' event. - try { - if (!process._exiting) { - process._exiting = true; - process.exitCode = kGenericUserError; - process.emit('exit', kGenericUserError); + } else { + // If no primary callback, try auxiliary callbacks (e.g., REPL) + // They must return true to indicate handling + let handled = false; + for (let i = exceptionHandlerState.auxiliaryCallbacks.length - 1; i >= 0; i--) { + if (exceptionHandlerState.auxiliaryCallbacks[i](er) === true) { + handled = true; + break; + } + } + if (!handled && !process.emit('uncaughtException', er, type)) { + // If someone handled it, then great. Otherwise, die in C++ land + // since that means that we'll exit the process, emit the 'exit' event. + try { + if (!process._exiting) { + process._exiting = true; + process.exitCode = kGenericUserError; + process.emit('exit', kGenericUserError); + } + } catch { + // Nothing to be done about it at this point. } - } catch { - // Nothing to be done about it at this point. + return false; } - return false; } // If we handled an error, then make sure any ticks get processed @@ -477,5 +509,6 @@ module.exports = { evalScript, onGlobalUncaughtException: createOnGlobalUncaughtException(), setUncaughtExceptionCaptureCallback, + addUncaughtExceptionCaptureCallback, hasUncaughtExceptionCaptureCallback, }; diff --git a/lib/repl.js b/lib/repl.js index 12f8074c78e524..3c33c73c413006 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -73,7 +73,6 @@ const { RegExpPrototypeExec, SafePromiseRace, SafeSet, - SafeWeakSet, StringPrototypeCharAt, StringPrototypeEndsWith, StringPrototypeIncludes, @@ -115,7 +114,7 @@ const { const { Console } = require('console'); const { shouldColorize } = require('internal/util/colors'); const CJSModule = require('internal/modules/cjs/loader').Module; -const domain = require('domain'); +const { AsyncLocalStorage } = require('async_hooks'); let debug = require('internal/util/debuglog').debuglog('repl', (fn) => { debug = fn; }); @@ -123,6 +122,7 @@ const { ErrorPrepareStackTrace, codes: { ERR_CANNOT_WATCH_SIGINT, + ERR_INVALID_ARG_VALUE, ERR_INVALID_REPL_EVAL_CONFIG, ERR_INVALID_REPL_INPUT, ERR_MISSING_ARGS, @@ -178,22 +178,47 @@ const { let processTopLevelAwait; const parentModule = module; -const domainSet = new SafeWeakSet(); + +// AsyncLocalStorage to track which REPL instance owns the current async context +// This replaces the domain-based tracking for error handling +const replContext = new AsyncLocalStorage(); +let exceptionCaptureSetup = false; + +/** + * Sets up the uncaught exception capture callback to route errors + * to the appropriate REPL instance. This replaces domain-based error handling. + * Uses addUncaughtExceptionCaptureCallback to coexist with the primary + * callback (e.g., domain module). + */ +function setupExceptionCapture() { + if (exceptionCaptureSetup) return; + + process.addUncaughtExceptionCaptureCallback((err) => { + const store = replContext.getStore(); + if (store?.replServer && !store.replServer.closed) { + store.replServer._handleError(err); + return true; // We handled it + } + // No active REPL context - let other handlers try + }); + + exceptionCaptureSetup = true; +} const kBufferedCommandSymbol = Symbol('bufferedCommand'); const kLoadingSymbol = Symbol('loading'); function processNewListener(event, listener) { - if (event === 'uncaughtException' && - process.domain && - listener.name !== 'domainUncaughtExceptionClear' && - domainSet.has(process.domain)) { - // Throw an error so that the event will not be added and the current - // domain takes over. That way the user is notified about the error - // and the current code evaluation is stopped, just as any other code - // that contains an error. - throw new ERR_INVALID_REPL_INPUT( - 'Listeners for `uncaughtException` cannot be used in the REPL'); + if (event === 'uncaughtException') { + const store = replContext.getStore(); + if (store?.replServer) { + // Throw an error so that the event will not be added and the + // current REPL handles it. That way the user is notified about + // the error and the current code evaluation is stopped, just as + // any other code that contains an error. + throw new ERR_INVALID_REPL_INPUT( + 'Listeners for `uncaughtException` cannot be used in the REPL'); + } } } @@ -341,7 +366,13 @@ class REPLServer extends Interface { this.allowBlockingCompletions = !!options.allowBlockingCompletions; this.useColors = !!options.useColors; - this._domain = options.domain || domain.create(); + this._isStandalone = !!options[kStandaloneREPL]; + + if (options.domain !== undefined) { + throw new ERR_INVALID_ARG_VALUE('options.domain', options.domain, + 'is no longer supported'); + } + this.useGlobal = !!useGlobal; this.ignoreUndefined = !!ignoreUndefined; this.replMode = replMode || module.exports.REPL_MODE_SLOPPY; @@ -370,7 +401,8 @@ class REPLServer extends Interface { this.once('exit', removeProcessNewListener); } - domainSet.add(this._domain); + // Set up exception capture for async error handling + setupExceptionCapture(); const savedRegExMatches = ['', '', '', '', '', '', '', '', '', '']; const sep = '\u0000\u0000\u0000'; @@ -591,13 +623,16 @@ class REPLServer extends Interface { } } catch (e) { err = e; - - if (process.domain) { - debug('not recoverable, send to domain'); + // If there's an active domain with error listeners, let it handle the error + if (process.domain?.listenerCount('error') > 0) { + debug('domain handling error'); process.domain.emit('error', err); - process.domain.exit(); return; } + // Handle non-recoverable errors directly + debug('not recoverable, handle error'); + self._handleError(err); + return; } if (awaitPromise && !err) { @@ -623,13 +658,15 @@ class REPLServer extends Interface { const result = (await promise)?.value; finishExecution(null, result); } catch (err) { - if (err && process.domain) { - debug('not recoverable, send to domain'); + // If there's an active domain with error listeners, let it handle the error + if (process.domain?.listenerCount('error') > 0) { + debug('domain handling async error'); process.domain.emit('error', err); - process.domain.exit(); - return; + } else { + // Handle non-recoverable async errors directly + debug('not recoverable, handle error'); + self._handleError(err); } - finishExecution(err); } finally { // Remove prioritized SIGINT listener if it was not called. prioritizedSigintQueue.delete(sigintListener); @@ -644,124 +681,16 @@ class REPLServer extends Interface { } } - self.eval = self._domain.bind(eval_); - - self._domain.on('error', function debugDomainError(e) { - debug('domain error'); - let errStack = ''; - - if (typeof e === 'object' && e !== null) { - overrideStackTrace.set(e, (error, stackFrames) => { - let frames; - if (typeof stackFrames === 'object') { - // Search from the bottom of the call stack to - // find the first frame with a null function name - const idx = ArrayPrototypeFindLastIndex( - stackFrames, - (frame) => frame.getFunctionName() === null, - ); - // If found, get rid of it and everything below it - frames = ArrayPrototypeSlice(stackFrames, 0, idx); - } else { - frames = stackFrames; - } - // FIXME(devsnek): this is inconsistent with the checks - // that the real prepareStackTrace dispatch uses in - // lib/internal/errors.js. - if (typeof MainContextError.prepareStackTrace === 'function') { - return MainContextError.prepareStackTrace(error, frames); - } - return ErrorPrepareStackTrace(error, frames); - }); - decorateErrorStack(e); - - if (e.domainThrown) { - delete e.domain; - delete e.domainThrown; - } - - if (isError(e)) { - if (e.stack) { - if (e.name === 'SyntaxError') { - // Remove stack trace. - e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( - /^\s+at\s.*\n?/gm, - SideEffectFreeRegExpPrototypeSymbolReplace(/^REPL\d+:\d+\r?\n/, e.stack, ''), - ''); - const importErrorStr = 'Cannot use import statement outside a ' + - 'module'; - if (StringPrototypeIncludes(e.message, importErrorStr)) { - e.message = 'Cannot use import statement inside the Node.js ' + - 'REPL, alternatively use dynamic import: ' + toDynamicImport(ArrayPrototypeAt(self.lines, -1)); - e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( - /SyntaxError:.*\n/, - e.stack, - `SyntaxError: ${e.message}\n`); - } - } else if (self.replMode === module.exports.REPL_MODE_STRICT) { - e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( - /(\s+at\s+REPL\d+:)(\d+)/, - e.stack, - (_, pre, line) => pre + (line - 1), - ); - } - } - errStack = self.writer(e); - - // Remove one line error braces to keep the old style in place. - if (errStack[0] === '[' && errStack[errStack.length - 1] === ']') { - errStack = StringPrototypeSlice(errStack, 1, -1); - } - } - } - - if (!self.underscoreErrAssigned) { - self.lastError = e; - } - - if (options[kStandaloneREPL] && - process.listenerCount('uncaughtException') !== 0) { - process.nextTick(() => { - process.emit('uncaughtException', e); - self.clearBufferedCommand(); - self.lines.level = []; - if (!self.closed) { - self.displayPrompt(); - } - }); - } else { - if (errStack === '') { - errStack = self.writer(e); - } - const lines = SideEffectFreeRegExpPrototypeSymbolSplit(/(?<=\n)/, errStack); - let matched = false; - - errStack = ''; - ArrayPrototypeForEach(lines, (line) => { - if (!matched && - RegExpPrototypeExec(/^\[?([A-Z][a-z0-9_]*)*Error/, line) !== null) { - errStack += writer.options.breakLength >= line.length ? - `Uncaught ${line}` : - `Uncaught:\n${line}`; - matched = true; - } else { - errStack += line; - } - }); - if (!matched) { - const ln = lines.length === 1 ? ' ' : ':\n'; - errStack = `Uncaught${ln}${errStack}`; - } - // Normalize line endings. - errStack += StringPrototypeEndsWith(errStack, '\n') ? '' : '\n'; - self.output.write(errStack); - self.clearBufferedCommand(); - self.lines.level = []; - if (!self.closed) { - self.displayPrompt(); - } - } - }); + // Wrap eval to run within the REPL's async context for error tracking. + // The function names are needed for stack trace filtering - they must not + // be anonymous, but we can't use 'eval' as a name since it's reserved. + const originalEval = eval_; + // eslint-disable-next-line func-name-matching + self.eval = function REPLEval(code, context, file, cb) { + replContext.run({ replServer: self }, function REPLEvalInContext() { + originalEval(code, context, file, cb); + }); + }; self.clearBufferedCommand(); @@ -925,7 +854,7 @@ class REPLServer extends Interface { } if (e) { - self._domain.emit('error', e.err || e); + self._handleError(e.err || e); self[kLastCommandErrored] = true; } @@ -1051,6 +980,117 @@ class REPLServer extends Interface { clearBufferedCommand() { this[kBufferedCommandSymbol] = ''; } + _handleError(e) { + debug('handle error'); + let errStack = ''; + + if (typeof e === 'object' && e !== null) { + overrideStackTrace.set(e, (error, stackFrames) => { + let frames; + if (typeof stackFrames === 'object') { + // Search from the bottom of the call stack to + // find the first frame with a null function name + const idx = ArrayPrototypeFindLastIndex( + stackFrames, + (frame) => frame.getFunctionName() === null, + ); + // If found, get rid of it and everything below it + frames = ArrayPrototypeSlice(stackFrames, 0, idx); + } else { + frames = stackFrames; + } + // FIXME(devsnek): this is inconsistent with the checks + // that the real prepareStackTrace dispatch uses in + // lib/internal/errors.js. + if (typeof MainContextError.prepareStackTrace === 'function') { + return MainContextError.prepareStackTrace(error, frames); + } + return ErrorPrepareStackTrace(error, frames); + }); + decorateErrorStack(e); + + if (isError(e)) { + if (e.stack) { + if (e.name === 'SyntaxError') { + // Remove stack trace. + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /^\s+at\s.*\n?/gm, + SideEffectFreeRegExpPrototypeSymbolReplace(/^REPL\d+:\d+\r?\n/, e.stack, ''), + ''); + const importErrorStr = 'Cannot use import statement outside a ' + + 'module'; + if (StringPrototypeIncludes(e.message, importErrorStr)) { + e.message = 'Cannot use import statement inside the Node.js ' + + 'REPL, alternatively use dynamic import: ' + toDynamicImport(ArrayPrototypeAt(this.lines, -1)); + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /SyntaxError:.*\n/, + e.stack, + `SyntaxError: ${e.message}\n`); + } + } else if (this.replMode === module.exports.REPL_MODE_STRICT) { + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /(\s+at\s+REPL\d+:)(\d+)/, + e.stack, + (_, pre, line) => pre + (line - 1), + ); + } + } + errStack = this.writer(e); + + // Remove one line error braces to keep the old style in place. + if (errStack[0] === '[' && errStack[errStack.length - 1] === ']') { + errStack = StringPrototypeSlice(errStack, 1, -1); + } + } + } + + if (!this.underscoreErrAssigned) { + this.lastError = e; + } + + if (this._isStandalone && + process.listenerCount('uncaughtException') !== 0) { + process.nextTick(() => { + process.emit('uncaughtException', e); + this.clearBufferedCommand(); + this.lines.level = []; + if (!this.closed) { + this.displayPrompt(); + } + }); + } else { + if (errStack === '') { + errStack = this.writer(e); + } + const lines = SideEffectFreeRegExpPrototypeSymbolSplit(/(?<=\n)/, errStack); + let matched = false; + + errStack = ''; + ArrayPrototypeForEach(lines, (line) => { + if (!matched && + RegExpPrototypeExec(/^\[?([A-Z][a-z0-9_]*)*Error/, line) !== null) { + errStack += writer.options.breakLength >= line.length ? + `Uncaught ${line}` : + `Uncaught:\n${line}`; + matched = true; + } else { + errStack += line; + } + }); + if (!matched) { + const ln = lines.length === 1 ? ' ' : ':\n'; + errStack = `Uncaught${ln}${errStack}`; + } + // Normalize line endings. + errStack += StringPrototypeEndsWith(errStack, '\n') ? '' : '\n'; + this.output.write(errStack); + this.clearBufferedCommand(); + this.lines.level = []; + if (!this.closed) { + this.displayPrompt(); + } + } + } close() { if (this.terminal && this.historyManager?.isFlushing && !this._closingOnFlush) { this._closingOnFlush = true; diff --git a/test/common/repl.js b/test/common/repl.js index 223050c76e1df0..6ce4d993a4c456 100644 --- a/test/common/repl.js +++ b/test/common/repl.js @@ -2,9 +2,8 @@ const ArrayStream = require('../common/arraystream'); const repl = require('node:repl'); -const assert = require('node:assert'); -function startNewREPLServer(replOpts = {}, testingOpts = {}) { +function startNewREPLServer(replOpts = {}) { const input = new ArrayStream(); const output = new ArrayStream(); @@ -20,11 +19,6 @@ function startNewREPLServer(replOpts = {}, testingOpts = {}) { ...replOpts, }); - if (!testingOpts.disableDomainErrorAssert) { - // Some errors are passed to the domain, but do not callback - replServer._domain.on('error', assert.ifError); - } - return { replServer, input, output }; } diff --git a/test/fixtures/repl-tab-completion-nested-repls.js b/test/fixtures/repl-tab-completion-nested-repls.js index 1d2b154f2b3341..79677491eca55f 100644 --- a/test/fixtures/repl-tab-completion-nested-repls.js +++ b/test/fixtures/repl-tab-completion-nested-repls.js @@ -1,6 +1,5 @@ // Tab completion sometimes uses a separate REPL instance under the hood. -// That REPL instance has its own domain. Make sure domain errors trickle back -// up to the main REPL. +// Make sure errors in completion callbacks are properly thrown. // // Ref: https://github.com/nodejs/node/issues/21586 @@ -31,11 +30,6 @@ const repl = require('repl'); const putIn = new ArrayStream(); const testMe = repl.start('', putIn); -// Some errors are passed to the domain, but do not callback. -testMe._domain.on('error', function(err) { - throw err; -}); - // Nesting of structures causes REPL to use a nested REPL for completion. putIn.run([ 'var top = function() {', diff --git a/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js b/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js index 4018220711517f..73f5f989b8e776 100644 --- a/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js +++ b/test/parallel/test-domain-load-after-set-uncaught-exception-capture.js @@ -1,17 +1,22 @@ 'use strict'; +// Tests that domain can be loaded after setUncaughtExceptionCaptureCallback +// has been called. This verifies that the mutual exclusivity has been removed. const common = require('../common'); -const assert = require('assert'); +// Set up a capture callback first process.setUncaughtExceptionCaptureCallback(common.mustNotCall()); -assert.throws( - () => require('domain'), - { - code: 'ERR_DOMAIN_CALLBACK_NOT_AVAILABLE', - name: 'Error', - message: /^A callback was registered.*with using the `domain` module/ - } -); +// Loading domain should not throw (coexistence is now supported) +const domain = require('domain'); + +// Verify domain module loaded successfully +const assert = require('assert'); +assert.ok(domain); +assert.ok(domain.create); +// Clean up process.setUncaughtExceptionCaptureCallback(null); -require('domain'); // Should not throw. + +// Domain should still be usable +const d = domain.create(); +assert.ok(d); diff --git a/test/parallel/test-domain-set-uncaught-exception-capture-after-load.js b/test/parallel/test-domain-set-uncaught-exception-capture-after-load.js index 4bf419d76eb453..64f129fd201781 100644 --- a/test/parallel/test-domain-set-uncaught-exception-capture-after-load.js +++ b/test/parallel/test-domain-set-uncaught-exception-capture-after-load.js @@ -1,30 +1,23 @@ 'use strict'; +// Tests that setUncaughtExceptionCaptureCallback can be called after domain +// is loaded. This verifies that the mutual exclusivity has been removed. const common = require('../common'); const assert = require('assert'); -Error.stackTraceLimit = Infinity; +// Load domain first +const domain = require('domain'); +assert.ok(domain); -(function foobar() { - require('domain'); -})(); +// Setting callback should not throw (coexistence is now supported) +process.setUncaughtExceptionCaptureCallback(common.mustNotCall()); -assert.throws( - () => process.setUncaughtExceptionCaptureCallback(common.mustNotCall()), - (err) => { - common.expectsError( - { - code: 'ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE', - name: 'Error', - message: /^The `domain` module is in use, which is mutually/ - } - )(err); +// Verify callback is registered +assert.ok(process.hasUncaughtExceptionCaptureCallback()); - assert(err.stack.includes('-'.repeat(40)), - `expected ${err.stack} to contain dashes`); +// Clean up +process.setUncaughtExceptionCaptureCallback(null); +assert.ok(!process.hasUncaughtExceptionCaptureCallback()); - const location = `at foobar (${__filename}:`; - assert(err.stack.includes(location), - `expected ${err.stack} to contain ${location}`); - return true; - } -); +// Domain should still be usable after callback operations +const d = domain.create(); +assert.ok(d); diff --git a/test/parallel/test-repl-eval-error-after-close.js b/test/parallel/test-repl-eval-error-after-close.js index 8c30a533efba15..0b4683fda4bfda 100644 --- a/test/parallel/test-repl-eval-error-after-close.js +++ b/test/parallel/test-repl-eval-error-after-close.js @@ -20,8 +20,6 @@ const assert = require('node:assert'); eval$.resolve(); }); }, - }, { - disableDomainErrorAssert: true, }); replServer.write('\n'); diff --git a/test/parallel/test-repl-let-process.js b/test/parallel/test-repl-let-process.js index eb6cbc6a472c72..22b57ab5bb977e 100644 --- a/test/parallel/test-repl-let-process.js +++ b/test/parallel/test-repl-let-process.js @@ -3,5 +3,5 @@ require('../common'); const { startNewREPLServer } = require('../common/repl'); // Regression test for https://github.com/nodejs/node/issues/6802 -const { input } = startNewREPLServer({ useGlobal: true }, { disableDomainErrorAssert: true }); +const { input } = startNewREPLServer({ useGlobal: true }); input.run(['let process']); diff --git a/test/parallel/test-repl-mode.js b/test/parallel/test-repl-mode.js index 3faa0a96d58799..4d614af1a16392 100644 --- a/test/parallel/test-repl-mode.js +++ b/test/parallel/test-repl-mode.js @@ -30,8 +30,8 @@ function testSloppyMode() { } function testStrictMode() { - const { input, output } = startNewREPLServer({ replMode: repl.REPL_MODE_STRICT, terminal: false, prompt: '> ' }, { - disableDomainErrorAssert: true, + const { input, output } = startNewREPLServer({ + replMode: repl.REPL_MODE_STRICT, terminal: false, prompt: '> ' }); input.emit('data', 'x = 3\n'); diff --git a/test/parallel/test-repl-multiple-instances-async-error.js b/test/parallel/test-repl-multiple-instances-async-error.js new file mode 100644 index 00000000000000..ddc8a5eaccdcca --- /dev/null +++ b/test/parallel/test-repl-multiple-instances-async-error.js @@ -0,0 +1,69 @@ +'use strict'; + +// This test verifies that when multiple REPL instances exist concurrently, +// async errors are correctly routed to the REPL instance that created them. + +const common = require('../common'); +const assert = require('assert'); +const repl = require('repl'); +const { Writable, PassThrough } = require('stream'); + +// Create two REPLs with separate inputs and outputs +let output1 = ''; +let output2 = ''; + +const input1 = new PassThrough(); +const input2 = new PassThrough(); + +const writable1 = new Writable({ + write(chunk, encoding, callback) { + output1 += chunk.toString(); + callback(); + } +}); + +const writable2 = new Writable({ + write(chunk, encoding, callback) { + output2 += chunk.toString(); + callback(); + } +}); + +const r1 = repl.start({ + input: input1, + output: writable1, + terminal: false, + prompt: 'R1> ', +}); + +const r2 = repl.start({ + input: input2, + output: writable2, + terminal: false, + prompt: 'R2> ', +}); + +// Create async error in REPL 1 +input1.write('setTimeout(() => { throw new Error("error from repl1") }, 10)\n'); + +// Create async error in REPL 2 +input2.write('setTimeout(() => { throw new Error("error from repl2") }, 20)\n'); + +setTimeout(common.mustCall(() => { + r1.close(); + r2.close(); + + // Verify error from REPL 1 went to REPL 1's output + assert.match(output1, /error from repl1/, + 'REPL 1 should have received its own async error'); + + // Verify error from REPL 2 went to REPL 2's output + assert.match(output2, /error from repl2/, + 'REPL 2 should have received its own async error'); + + // Verify errors did not cross over to wrong REPL + assert.doesNotMatch(output1, /error from repl2/, + 'REPL 1 should not have received REPL 2\'s error'); + assert.doesNotMatch(output2, /error from repl1/, + 'REPL 2 should not have received REPL 1\'s error'); +}), 100); diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js index 82df8ff4fc6335..0efb814f38d2b5 100644 --- a/test/parallel/test-repl-pretty-custom-stack.js +++ b/test/parallel/test-repl-pretty-custom-stack.js @@ -10,8 +10,6 @@ function run({ command, expected }) { const { replServer, output } = startNewREPLServer({ terminal: false, useColors: false - }, { - disableDomainErrorAssert: true, }); replServer.write(`${command}\n`); diff --git a/test/parallel/test-repl-pretty-stack-custom-writer.js b/test/parallel/test-repl-pretty-stack-custom-writer.js index 2d39633030d775..e31460dbc93efb 100644 --- a/test/parallel/test-repl-pretty-stack-custom-writer.js +++ b/test/parallel/test-repl-pretty-stack-custom-writer.js @@ -5,10 +5,7 @@ const { startNewREPLServer } = require('../common/repl'); const testingReplPrompt = '_REPL_TESTING_PROMPT_>'; -const { replServer, output } = startNewREPLServer( - { prompt: testingReplPrompt }, - { disableDomainErrorAssert: true } -); +const { replServer, output } = startNewREPLServer({ prompt: testingReplPrompt }); replServer.write('throw new Error("foo[a]")\n'); diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js index a7f13dea75aaea..b2f9cc82c08df0 100644 --- a/test/parallel/test-repl-pretty-stack.js +++ b/test/parallel/test-repl-pretty-stack.js @@ -7,14 +7,11 @@ const { startNewREPLServer } = require('../common/repl'); const stackRegExp = /(at .*REPL\d+:)[0-9]+:[0-9]+/g; function run({ command, expected, ...extraREPLOptions }, i) { - const { replServer, output } = startNewREPLServer( - { - terminal: false, - useColors: false, - ...extraREPLOptions - }, - { disableDomainErrorAssert: true } - ); + const { replServer, output } = startNewREPLServer({ + terminal: false, + useColors: false, + ...extraREPLOptions + }); replServer.write(`${command}\n`); if (typeof expected === 'string') { diff --git a/test/parallel/test-repl-preview-newlines.js b/test/parallel/test-repl-preview-newlines.js index 22ffe0db108590..34a944beb538d7 100644 --- a/test/parallel/test-repl-preview-newlines.js +++ b/test/parallel/test-repl-preview-newlines.js @@ -6,9 +6,7 @@ const { startNewREPLServer } = require('../common/repl'); common.skipIfInspectorDisabled(); -const { input, output } = startNewREPLServer( - { useColors: true }, { disableDomainErrorAssert: true } -); +const { input, output } = startNewREPLServer({ useColors: true }); output.accumulator = ''; diff --git a/test/parallel/test-repl-syntax-error-stack.js b/test/parallel/test-repl-syntax-error-stack.js index 1b6e3fb6e879f2..16bf27d045bc77 100644 --- a/test/parallel/test-repl-syntax-error-stack.js +++ b/test/parallel/test-repl-syntax-error-stack.js @@ -11,7 +11,7 @@ process.on('exit', () => { assert.strictEqual(found, true); }); -const { input, output } = startNewREPLServer({}, { disableDomainErrorAssert: true }); +const { input, output } = startNewREPLServer(); output.write = (data) => { // Matching only on a minimal piece of the stack because the string will vary diff --git a/test/parallel/test-repl-tab-complete-crash.js b/test/parallel/test-repl-tab-complete-crash.js index 58628eb85b2a38..29f75028bdac94 100644 --- a/test/parallel/test-repl-tab-complete-crash.js +++ b/test/parallel/test-repl-tab-complete-crash.js @@ -4,7 +4,7 @@ const common = require('../common'); const assert = require('assert'); const { startNewREPLServer } = require('../common/repl'); -const { replServer, input } = startNewREPLServer({}, { disableDomainErrorAssert: true }); +const { replServer, input } = startNewREPLServer(); // https://github.com/nodejs/node/issues/3346 // Tab-completion should be empty diff --git a/test/parallel/test-repl-tab.js b/test/parallel/test-repl-tab.js index e99f667c4a38f5..710fca9fae2d1e 100644 --- a/test/parallel/test-repl-tab.js +++ b/test/parallel/test-repl-tab.js @@ -10,6 +10,4 @@ const testMe = repl.start('', putIn, function(cmd, context, filename, callback(null, cmd); }); -testMe._domain.on('error', common.mustNotCall()); - testMe.complete('', common.mustSucceed()); diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index 0b35443dbdce14..a94ff8e48984a3 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -180,7 +180,7 @@ async function ordinaryTests() { ['k', '234'], ['const k = await Promise.resolve(345)', "Uncaught SyntaxError: Identifier 'k' has already been declared"], // Regression test for https://github.com/nodejs/node/issues/43777. - ['await Promise.resolve(123), Promise.resolve(456)', 'Promise {', { line: 0 }], + ['await Promise.resolve(123), Promise.resolve(456)', 'Promise { 456 }'], ['await Promise.resolve(123), await Promise.resolve(456)', '456'], ['await (Promise.resolve(123), Promise.resolve(456))', '456'], ]; diff --git a/test/parallel/test-repl-uncaught-exception-async.js b/test/parallel/test-repl-uncaught-exception-async.js index f4180080f496f7..e5373cdaca4d8d 100644 --- a/test/parallel/test-repl-uncaught-exception-async.js +++ b/test/parallel/test-repl-uncaught-exception-async.js @@ -8,17 +8,12 @@ const common = require('../common'); const assert = require('assert'); const { startNewREPLServer } = require('../common/repl'); -const { replServer, output } = startNewREPLServer( - { - prompt: '', - terminal: false, - useColors: false, - global: false, - }, - { - disableDomainErrorAssert: true - }, -); +const { replServer, output } = startNewREPLServer({ + prompt: '', + terminal: false, + useColors: false, + global: false, +}); replServer.write( 'process.nextTick(() => {\n' + diff --git a/test/parallel/test-repl-uncaught-exception-evalcallback.js b/test/parallel/test-repl-uncaught-exception-evalcallback.js index 77d03320ee9375..844fce6995aaa6 100644 --- a/test/parallel/test-repl-uncaught-exception-evalcallback.js +++ b/test/parallel/test-repl-uncaught-exception-evalcallback.js @@ -3,21 +3,16 @@ const common = require('../common'); const assert = require('assert'); const { startNewREPLServer } = require('../common/repl'); -const { replServer, output } = startNewREPLServer( - { - prompt: '', - terminal: false, - useColors: false, - global: false, - eval: common.mustCall((code, context, filename, cb) => { - replServer.setPrompt('prompt! '); - cb(new Error('err')); - }) - }, - { - disableDomainErrorAssert: true - }, -); +const { replServer, output } = startNewREPLServer({ + prompt: '', + terminal: false, + useColors: false, + global: false, + eval: common.mustCall((code, context, filename, cb) => { + replServer.setPrompt('prompt! '); + cb(new Error('err')); + }) +}); replServer.write('foo\n'); diff --git a/test/parallel/test-repl-uncaught-exception.js b/test/parallel/test-repl-uncaught-exception.js index 7753fe180b07fd..012c7f59ebc8a8 100644 --- a/test/parallel/test-repl-uncaught-exception.js +++ b/test/parallel/test-repl-uncaught-exception.js @@ -6,16 +6,11 @@ const { startNewREPLServer } = require('../common/repl'); let count = 0; function run({ command, expected, useColors = false }) { - const { replServer, output } = startNewREPLServer( - { - prompt: '', - terminal: false, - useColors, - }, - { - disableDomainErrorAssert: true - }, - ); + const { replServer, output } = startNewREPLServer({ + prompt: '', + terminal: false, + useColors, + }); replServer.write(`${command}\n`); diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index 4c091a268fb701..c9ae7ca0e7ca0c 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -138,8 +138,6 @@ function testError() { prompt: testingReplPrompt, replMode: repl.REPL_MODE_STRICT, preview: false, - }, { - disableDomainErrorAssert: true }); replServer.write(`_error; // initial value undefined diff --git a/test/pummel/test-repl-paste-big-data.js b/test/pummel/test-repl-paste-big-data.js index 2265a1af8e393c..46f8415a2b0aae 100644 --- a/test/pummel/test-repl-paste-big-data.js +++ b/test/pummel/test-repl-paste-big-data.js @@ -8,7 +8,7 @@ const { startNewREPLServer } = require('../common/repl'); const cpuUsage = process.cpuUsage(); -const { replServer } = startNewREPLServer({}, { disableDomainErrorAssert: true }); +const { replServer } = startNewREPLServer(); replServer.input.emit('data', '{}'); replServer.input.emit('keypress', '', { name: 'left' }); replServer.input.emit('data', 'node'); From e4c164e045fbca4981d555257d92aabd7acf6dfd Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 9 Mar 2026 22:20:08 +0100 Subject: [PATCH 003/106] repl: handle exceptions from async context after close a9da9ffc04c923f383 recently restructured async context handling in the REPL source so that it no longer uses the domain module, and instead performs its own async context tracking. That change was not intended to be breaking, but it affected behavior for uncaught exceptions thrown after the REPL was closed. Those would now be treated as uncaught exceptions on the process level, which is probably not intentional in most situations. While it's understandably not great that we handle execptions after closing the REPL instance, I am confident that it's best to restore the previous behavior for now and add more granular handling options separately and intentionally in a (potentially semver-major) follow-up change. Refs: https://github.com/nodejs/node/pull/61227 PR-URL: https://github.com/nodejs/node/pull/62165 Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/repl.js | 7 +++++- ...pl-uncaught-exception-after-input-ended.js | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-repl-uncaught-exception-after-input-ended.js diff --git a/lib/repl.js b/lib/repl.js index 3c33c73c413006..e747cc581cc8eb 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -195,7 +195,12 @@ function setupExceptionCapture() { process.addUncaughtExceptionCaptureCallback((err) => { const store = replContext.getStore(); - if (store?.replServer && !store.replServer.closed) { + // TODO(addaleax): Add back a `store.replServer.closed` check here + // as a semver-major change. + // This check may need to allow for an opt-out, since the change in + // behavior could lead to DoS vulnerabilities (e.g. in the case of + // the net-based REPL described in our docs). + if (store?.replServer) { store.replServer._handleError(err); return true; // We handled it } diff --git a/test/parallel/test-repl-uncaught-exception-after-input-ended.js b/test/parallel/test-repl-uncaught-exception-after-input-ended.js new file mode 100644 index 00000000000000..1e2ca86a9f079c --- /dev/null +++ b/test/parallel/test-repl-uncaught-exception-after-input-ended.js @@ -0,0 +1,23 @@ +'use strict'; +const common = require('../common'); +const { start } = require('node:repl'); +const { PassThrough } = require('node:stream'); +const assert = require('node:assert'); + +// This test verifies that uncaught exceptions in the REPL +// do not bring down the process, even if stdin may already +// have been ended at that point (and the REPL closed as +// a result of that). +const input = new PassThrough(); +const output = new PassThrough().setEncoding('utf8'); +start({ + input, + output, + terminal: false, +}); + +input.end('setImmediate(() => { throw new Error("test"); });\n'); + +setImmediate(common.mustCall(() => { + assert.match(output.read(), /Uncaught Error: test/); +})); From 0250b436ee219c41b1dd8de8026985189f1e06a6 Mon Sep 17 00:00:00 2001 From: Stefan Stojanovic Date: Tue, 10 Mar 2026 15:11:23 +0100 Subject: [PATCH 004/106] fs: fix cpSync to handle non-ASCII characters Fixes: https://github.com/nodejs/node/issues/61878 PR-URL: https://github.com/nodejs/node/pull/61950 Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- src/node_file.cc | 16 +++++++++---- .../parallel/test-fs-cp-sync-unicode-dest.mjs | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 test/parallel/test-fs-cp-sync-unicode-dest.mjs diff --git a/src/node_file.cc b/src/node_file.cc index ef83a43d9f07f2..b9e7aba56e9ad1 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -3432,15 +3432,18 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo& args) { THROW_IF_INSUFFICIENT_PERMISSIONS( env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView()); + auto src_path = src.ToPath(); + auto dest_path = dest.ToPath(); + std::error_code error; - if (!std::filesystem::remove(*dest, error)) { + if (!std::filesystem::remove(dest_path, error)) { return env->ThrowStdErrException(error, "unlink", *dest); } if (mode == 0) { // if no mode is specified use the faster std::filesystem API - if (!std::filesystem::copy_file(*src, *dest, error)) { + if (!std::filesystem::copy_file(src_path, dest_path, error)) { return env->ThrowStdErrException(error, "cp", *dest); } } else { @@ -3453,7 +3456,7 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo& args) { } if (preserve_timestamps) { - CopyUtimes(*src, *dest, env); + CopyUtimes(src_path, dest_path, env); } } @@ -3496,8 +3499,11 @@ static void CpSyncCopyDir(const FunctionCallbackInfo& args) { bool verbatim_symlinks = args[5]->IsTrue(); bool preserve_timestamps = args[6]->IsTrue(); + auto src_path = src.ToPath(); + auto dest_path = dest.ToPath(); + std::error_code error; - std::filesystem::create_directories(*dest, error); + std::filesystem::create_directories(dest_path, error); if (error) { return env->ThrowStdErrException(error, "cp", *dest); } @@ -3639,7 +3645,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo& args) { return true; }; - copy_dir_contents(std::filesystem::path(*src), std::filesystem::path(*dest)); + copy_dir_contents(src_path, dest_path); } BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile( diff --git a/test/parallel/test-fs-cp-sync-unicode-dest.mjs b/test/parallel/test-fs-cp-sync-unicode-dest.mjs new file mode 100644 index 00000000000000..0638b98180c5da --- /dev/null +++ b/test/parallel/test-fs-cp-sync-unicode-dest.mjs @@ -0,0 +1,23 @@ +// Regression test for https://github.com/nodejs/node/issues/61878 +// fs.cpSync should copy files when destination path has UTF characters. +import '../common/index.mjs'; +import { cpSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import assert from 'node:assert'; +import tmpdir from '../common/tmpdir.js'; + +tmpdir.refresh(); + +const src = join(tmpdir.path, 'src'); +mkdirSync(join(src, 'subdir'), { recursive: true }); +writeFileSync(join(src, 'file1.txt'), 'Hello World'); +writeFileSync(join(src, 'subdir', 'nested.txt'), 'Nested File'); + +const dest = join(tmpdir.path, 'Eyjafjallajökull-Pranckevičius'); +cpSync(src, dest, { recursive: true, force: true }); + +const destFiles = readdirSync(dest); +assert.ok(destFiles.includes('file1.txt')); +assert.strictEqual(readFileSync(join(dest, 'file1.txt'), 'utf8'), 'Hello World'); +assert.ok(destFiles.includes('subdir')); +assert.strictEqual(readFileSync(join(dest, 'subdir', 'nested.txt'), 'utf8'), 'Nested File'); From f0eea0f905b5d7c92dbdcaad1dca2bb339cb13ee Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Thu, 5 Mar 2026 15:49:43 +0100 Subject: [PATCH 005/106] build: fix --node-builtin-modules-path PR-URL: https://github.com/nodejs/node/pull/62115 Reviewed-By: Joyee Cheung Reviewed-By: Yagiz Nizipli --- node.gyp | 18 +++++++++++++++++- src/node_builtins.cc | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/node.gyp b/node.gyp index 2dd7eb1af5865a..1366e1a0cd3505 100644 --- a/node.gyp +++ b/node.gyp @@ -948,7 +948,13 @@ }, }], [ 'node_builtin_modules_path!=""', { - 'defines': [ 'NODE_BUILTIN_MODULES_PATH="<(node_builtin_modules_path)"' ] + 'defines': [ 'NODE_BUILTIN_MODULES_PATH="<(node_builtin_modules_path)"' ], + # When loading builtins from disk, JS source files do not need to + # trigger rebuilds since the binary reads them at runtime. + 'sources!': [ + '<@(library_files)', + '<@(deps_files)', + ], }], [ 'node_shared=="true"', { 'sources': [ @@ -1103,6 +1109,16 @@ '<@(deps_files)', 'config.gypi' ], + 'conditions': [ + [ 'node_builtin_modules_path!=""', { + # When loading builtins from disk, JS source files do not need + # to trigger rebuilds since the binary reads them at runtime. + 'inputs!': [ + '<@(library_files)', + '<@(deps_files)', + ], + }], + ], 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/node_javascript.cc', ], diff --git a/src/node_builtins.cc b/src/node_builtins.cc index 5ef8d06933700c..318ff5158e9c28 100644 --- a/src/node_builtins.cc +++ b/src/node_builtins.cc @@ -74,7 +74,8 @@ const BuiltinSource* BuiltinLoader::AddFromDisk(const char* id, const std::string& filename, const UnionBytes& source) { BuiltinSourceType type = GetBuiltinSourceType(id, filename); - auto result = source_.write()->emplace(id, BuiltinSource{id, source, type}); + auto result = + source_.write()->insert_or_assign(id, BuiltinSource{id, source, type}); return &(result.first->second); } From 966b700623aa0232925a1f05e1da5081e493cad8 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 10 Mar 2026 23:37:10 +0100 Subject: [PATCH 006/106] sea: support code cache for ESM entrypoint in SEA The initial support for ESM entrypoint in SEA didn't support code cache. This patch implements that by following a path similar to how code cache in CJS SEA entrypoint is supported: at build time we generate the code cache from C++ and put it into the sea blob, and at runtime we consume it via a special case in compilation routines - for CJS this was CompileFunctionForCJSLoader, in the case of SourceTextModule, it's in Module::New. PR-URL: https://github.com/nodejs/node/pull/62158 Refs: https://github.com/nodejs/node/pull/61813 Reviewed-By: Matteo Collina Reviewed-By: Anna Henningsen --- doc/api/single-executable-applications.md | 3 +- src/module_wrap.cc | 42 ++++++-- src/node_sea.cc | 98 ++++++++++++------- .../sea/esm-code-cache/sea-config.json | 7 ++ test/fixtures/sea/esm-code-cache/sea.mjs | 20 ++++ ...e-executable-application-esm-code-cache.js | 34 +++++++ 6 files changed, 159 insertions(+), 45 deletions(-) create mode 100644 test/fixtures/sea/esm-code-cache/sea-config.json create mode 100644 test/fixtures/sea/esm-code-cache/sea.mjs create mode 100644 test/sea/test-single-executable-application-esm-code-cache.js diff --git a/doc/api/single-executable-applications.md b/doc/api/single-executable-applications.md index 015e1d048bd268..c63b8c8f57c0c3 100644 --- a/doc/api/single-executable-applications.md +++ b/doc/api/single-executable-applications.md @@ -395,8 +395,7 @@ The accepted values are: If the `mainFormat` field is not specified, it defaults to `"commonjs"`. -Currently, `"mainFormat": "module"` cannot be used together with `"useSnapshot"` -or `"useCodeCache"`. +Currently, `"mainFormat": "module"` cannot be used together with `"useSnapshot"`. ### Module loading in the injected main script diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 354b45bda9ccc7..ef69fe133fad61 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -1,5 +1,6 @@ #include "module_wrap.h" +#include "debug_utils-inl.h" #include "env.h" #include "memory_tracker-inl.h" #include "node_contextify.h" @@ -7,6 +8,7 @@ #include "node_external_reference.h" #include "node_internals.h" #include "node_process-inl.h" +#include "node_sea.h" #include "node_url.h" #include "node_watchdog.h" #include "util-inl.h" @@ -365,6 +367,20 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { new ScriptCompiler::CachedData(data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength()); } +#ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION + // For embedder ESM in a SEA, use the bundled code cache if available. + if (id_symbol == realm->isolate_data()->embedder_module_hdo() && + sea::IsSingleExecutable()) { + sea::SeaResource sea = sea::FindSingleExecutableResource(); + if (sea.use_code_cache()) { + std::string_view data = sea.code_cache.value(); + user_cached_data = new ScriptCompiler::CachedData( + reinterpret_cast(data.data()), + static_cast(data.size()), + ScriptCompiler::CachedData::BufferNotOwned); + } + } +#endif // !DISABLE_SINGLE_EXECUTABLE_APPLICATION Local source_text = args[2].As(); bool cache_rejected = false; @@ -389,12 +405,26 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { return; } - if (user_cached_data.has_value() && user_cached_data.value() != nullptr && - cache_rejected) { - THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED( - realm, "cachedData buffer was rejected"); - try_catch.ReThrow(); - return; + if (user_cached_data.has_value() && user_cached_data.value() != nullptr) { +#ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION + if (id_symbol == realm->isolate_data()->embedder_module_hdo() && + sea::IsSingleExecutable()) { + if (cache_rejected) { + per_process::Debug(DebugCategory::SEA, + "SEA module code cache rejected\n"); + ProcessEmitWarningSync(realm->env(), "Code cache data rejected."); + } else { + per_process::Debug(DebugCategory::SEA, + "SEA module code cache accepted\n"); + } + } else // NOLINT(readability/braces) +#endif // !DISABLE_SINGLE_EXECUTABLE_APPLICATION + if (cache_rejected) { + THROW_ERR_VM_MODULE_CACHED_DATA_REJECTED( + realm, "cachedData buffer was rejected"); + try_catch.ReThrow(); + return; + } } if (that->Set(context, diff --git a/src/node_sea.cc b/src/node_sea.cc index 1f340cf56b21aa..1be41e6f14146e 100644 --- a/src/node_sea.cc +++ b/src/node_sea.cc @@ -24,6 +24,7 @@ using v8::Array; using v8::ArrayBuffer; using v8::BackingStore; using v8::Context; +using v8::Data; using v8::Function; using v8::FunctionCallbackInfo; using v8::HandleScope; @@ -31,11 +32,13 @@ using v8::Isolate; using v8::Local; using v8::LocalVector; using v8::MaybeLocal; +using v8::Module; using v8::NewStringType; using v8::Object; using v8::ScriptCompiler; using v8::ScriptOrigin; using v8::String; +using v8::UnboundModuleScript; using v8::Value; namespace node { @@ -542,7 +545,7 @@ std::optional ParseSingleExecutableConfig( "\"useCodeCache\" is redundant when \"useSnapshot\" is true\n"); } - // TODO(joyeecheung): support ESM with useSnapshot and useCodeCache. + // TODO(joyeecheung): support ESM with useSnapshot. if (result.main_format == ModuleFormat::kModule && static_cast(result.flags & SeaFlags::kUseSnapshot)) { FPrintF(stderr, @@ -551,14 +554,6 @@ std::optional ParseSingleExecutableConfig( return std::nullopt; } - if (result.main_format == ModuleFormat::kModule && - static_cast(result.flags & SeaFlags::kUseCodeCache)) { - FPrintF(stderr, - "\"mainFormat\": \"module\" is not supported when " - "\"useCodeCache\" is true\n"); - return std::nullopt; - } - if (result.main_path.empty()) { FPrintF(stderr, "\"main\" field of %s is not a non-empty string\n", @@ -616,7 +611,8 @@ ExitCode GenerateSnapshotForSEA(const SeaConfig& config, } std::optional GenerateCodeCache(std::string_view main_path, - std::string_view main_script) { + std::string_view main_script, + ModuleFormat format) { RAIIIsolate raii_isolate(SnapshotBuilder::GetEmbeddedSnapshotData()); Isolate* isolate = raii_isolate.get(); @@ -647,34 +643,62 @@ std::optional GenerateCodeCache(std::string_view main_path, return std::nullopt; } - LocalVector parameters( - isolate, - { - FIXED_ONE_BYTE_STRING(isolate, "exports"), - FIXED_ONE_BYTE_STRING(isolate, "require"), - FIXED_ONE_BYTE_STRING(isolate, "module"), - FIXED_ONE_BYTE_STRING(isolate, "__filename"), - FIXED_ONE_BYTE_STRING(isolate, "__dirname"), - }); - ScriptOrigin script_origin(filename, 0, 0, true); - ScriptCompiler::Source script_source(content, script_origin); - MaybeLocal maybe_fn = - ScriptCompiler::CompileFunction(context, - &script_source, - parameters.size(), - parameters.data(), - 0, - nullptr); - Local fn; - if (!maybe_fn.ToLocal(&fn)) { - return std::nullopt; + std::unique_ptr cache; + + if (format == ModuleFormat::kModule) { + // Using empty host defined options is fine as it is not part of the cache + // key and will be reset after deserialization. + ScriptOrigin origin(filename, + 0, // line offset + 0, // column offset + true, // is cross origin + -1, // script id + Local(), // source map URL + false, // is opaque + false, // is WASM + true, // is ES Module + Local()); // host defined options + ScriptCompiler::Source source(content, origin); + Local module; + if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { + return std::nullopt; + } + Local unbound = module->GetUnboundModuleScript(); + cache.reset(ScriptCompiler::CreateCodeCache(unbound)); + } else { + // TODO(RaisinTen): Using the V8 code cache prevents us from using + // `import()` in the SEA code. Support it. Refs: + // https://github.com/nodejs/node/pull/48191#discussion_r1213271430 + // TODO(joyeecheung): this likely has been fixed by + // https://chromium-review.googlesource.com/c/v8/v8/+/5401780 - add a test + // and update docs. + LocalVector parameters( + isolate, + { + FIXED_ONE_BYTE_STRING(isolate, "exports"), + FIXED_ONE_BYTE_STRING(isolate, "require"), + FIXED_ONE_BYTE_STRING(isolate, "module"), + FIXED_ONE_BYTE_STRING(isolate, "__filename"), + FIXED_ONE_BYTE_STRING(isolate, "__dirname"), + }); + ScriptOrigin script_origin(filename, 0, 0, true); + ScriptCompiler::Source script_source(content, script_origin); + Local fn; + if (!ScriptCompiler::CompileFunction(context, + &script_source, + parameters.size(), + parameters.data(), + 0, + nullptr) + .ToLocal(&fn)) { + return std::nullopt; + } + cache.reset(ScriptCompiler::CreateCodeCacheForFunction(fn)); } - // TODO(RaisinTen): Using the V8 code cache prevents us from using `import()` - // in the SEA code. Support it. - // Refs: https://github.com/nodejs/node/pull/48191#discussion_r1213271430 - std::unique_ptr cache{ - ScriptCompiler::CreateCodeCacheForFunction(fn)}; + if (!cache) { + return std::nullopt; + } std::string code_cache(cache->data, cache->data + cache->length); return code_cache; } @@ -728,7 +752,7 @@ ExitCode GenerateSingleExecutableBlob( std::string code_cache; if (static_cast(config.flags & SeaFlags::kUseCodeCache)) { std::optional optional_code_cache = - GenerateCodeCache(config.main_path, main_script); + GenerateCodeCache(config.main_path, main_script, config.main_format); if (!optional_code_cache.has_value()) { FPrintF(stderr, "Cannot generate V8 code cache\n"); return ExitCode::kGenericUserError; diff --git a/test/fixtures/sea/esm-code-cache/sea-config.json b/test/fixtures/sea/esm-code-cache/sea-config.json new file mode 100644 index 00000000000000..53ba60cc157bde --- /dev/null +++ b/test/fixtures/sea/esm-code-cache/sea-config.json @@ -0,0 +1,7 @@ +{ + "main": "sea.mjs", + "output": "sea", + "mainFormat": "module", + "useCodeCache": true, + "disableExperimentalSEAWarning": true +} diff --git a/test/fixtures/sea/esm-code-cache/sea.mjs b/test/fixtures/sea/esm-code-cache/sea.mjs new file mode 100644 index 00000000000000..b2605a30ed0b63 --- /dev/null +++ b/test/fixtures/sea/esm-code-cache/sea.mjs @@ -0,0 +1,20 @@ +import assert from 'node:assert'; +import { createRequire } from 'node:module'; +import { pathToFileURL } from 'node:url'; +import { dirname } from 'node:path'; + +// Test createRequire with process.execPath. +const assert2 = createRequire(process.execPath)('node:assert'); +assert.strictEqual(assert2.strict, assert.strict); + +// Test import.meta properties. +assert.strictEqual(import.meta.url, pathToFileURL(process.execPath).href); +assert.strictEqual(import.meta.filename, process.execPath); +assert.strictEqual(import.meta.dirname, dirname(process.execPath)); +assert.strictEqual(import.meta.main, true); + +// Test import() with a built-in module. +const { strict } = await import('node:assert'); +assert.strictEqual(strict, assert.strict); + +console.log('ESM SEA with code cache executed successfully'); diff --git a/test/sea/test-single-executable-application-esm-code-cache.js b/test/sea/test-single-executable-application-esm-code-cache.js new file mode 100644 index 00000000000000..1fe6dff7a3da25 --- /dev/null +++ b/test/sea/test-single-executable-application-esm-code-cache.js @@ -0,0 +1,34 @@ +'use strict'; + +// This tests the creation of a single executable application with an ESM +// entry point using "mainFormat": "module" and "useCodeCache": true. + +require('../common'); + +const { + buildSEA, + skipIfBuildSEAIsNotSupported, +} = require('../common/sea'); + +skipIfBuildSEAIsNotSupported(); + +const tmpdir = require('../common/tmpdir'); +const fixtures = require('../common/fixtures'); +const { spawnSyncAndExitWithoutError } = require('../common/child_process'); + +tmpdir.refresh(); + +const outputFile = buildSEA(fixtures.path('sea', 'esm-code-cache')); + +spawnSyncAndExitWithoutError( + outputFile, + { + env: { + NODE_DEBUG_NATIVE: 'SEA', + ...process.env, + }, + }, + { + stdout: /ESM SEA with code cache executed successfully/, + stderr: /SEA module code cache accepted/, + }); From 7d9db8cd212be8c008279d822e567542938b423c Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 11 Mar 2026 15:15:24 +0100 Subject: [PATCH 007/106] tools: keep GN files when updating Merve PR-URL: https://github.com/nodejs/node/pull/62167 Reviewed-By: Shelley Vohr Reviewed-By: Chengzhong Wu Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- tools/dep_updaters/update-merve.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/dep_updaters/update-merve.sh b/tools/dep_updaters/update-merve.sh index ec0525aadb48b6..31d9b15148ad5d 100755 --- a/tools/dep_updaters/update-merve.sh +++ b/tools/dep_updaters/update-merve.sh @@ -54,8 +54,8 @@ rm "$MERVE_ZIP" curl -sL -o "$MERVE_LICENSE" "https://raw.githubusercontent.com/anonrig/merve/HEAD/LICENSE-MIT" -echo "Replacing existing merve (except GYP build files)" -mv "$DEPS_DIR/merve/merve.gyp" "$WORKSPACE/" +echo "Replacing existing merve (except GYP/GN build files)" +mv "$DEPS_DIR/merve/merve.gyp" "$DEPS_DIR/merve/BUILD.gn" "$DEPS_DIR/merve/unofficial.gni" "$WORKSPACE/" rm -rf "$DEPS_DIR/merve" mv "$WORKSPACE" "$DEPS_DIR/merve" From 93d77719e8e915255d968a3d0af4ce0537f7f1ec Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 11 Mar 2026 19:23:21 +0100 Subject: [PATCH 008/106] crypto: read algorithm name property only once in normalizeAlgorithm PR-URL: https://github.com/nodejs/node/pull/62170 Refs: https://redirect.github.com/web-platform-tests/wpt/pull/57614#pullrequestreview-3808145365 Reviewed-By: Yagiz Nizipli Reviewed-By: Colin Ihrig --- lib/internal/crypto/util.js | 11 ++++++---- test/parallel/test-webcrypto-util.js | 32 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index 5ec1d409ec05b9..96abe6a04b28e1 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -565,10 +565,13 @@ function normalizeAlgorithm(algorithm, op) { return { name: algName }; // 6. - const normalizedAlgorithm = webidl.converters[desiredType](algorithm, { - prefix: 'Failed to normalize algorithm', - context: 'passed algorithm', - }); + const normalizedAlgorithm = webidl.converters[desiredType]( + { __proto__: algorithm, name: algName }, + { + prefix: 'Failed to normalize algorithm', + context: 'passed algorithm', + }, + ); // 7. normalizedAlgorithm.name = algName; diff --git a/test/parallel/test-webcrypto-util.js b/test/parallel/test-webcrypto-util.js index b8d5361433fd0e..89d8575e20ddbd 100644 --- a/test/parallel/test-webcrypto-util.js +++ b/test/parallel/test-webcrypto-util.js @@ -17,3 +17,35 @@ const { assert.strictEqual(normalizeAlgorithm(algorithm, 'sign') !== algorithm, true); assert.deepStrictEqual(algorithm, { name: 'ECDSA', hash: 'SHA-256' }); } + +// The algorithm name getter should only be invoked once during +// normalizeAlgorithm, including for algorithms with a non-null desiredType +// where step 6 runs the specialized dictionary converter. +// Refs: https://github.com/web-platform-tests/wpt/pull/57614#pullrequestreview-3808145365 +{ + let nameReadCount = 0; + const algorithm = { + get name() { + nameReadCount++; + return 'AES-GCM'; + }, + iv: new Uint8Array(12), + }; + const normalized = normalizeAlgorithm(algorithm, 'encrypt'); + assert.strictEqual(normalized.name, 'AES-GCM'); + assert.strictEqual(nameReadCount, 1); +} + +{ + let nameReadCount = 0; + const algorithm = { + get name() { + nameReadCount++; + return 'ECDSA'; + }, + hash: 'SHA-256', + }; + const normalized = normalizeAlgorithm(algorithm, 'sign'); + assert.strictEqual(normalized.name, 'ECDSA'); + assert.strictEqual(nameReadCount, 1); +} From 4d96e535703af0245b7a98e1bab1f155c5cbd33b Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 11 Mar 2026 19:43:14 +0100 Subject: [PATCH 009/106] crypto: refactor WebCrypto AEAD algorithms auth tag handling PR-URL: https://github.com/nodejs/node/pull/62169 Reviewed-By: Yagiz Nizipli Reviewed-By: Colin Ihrig --- lib/internal/crypto/aes.js | 64 ++----------- lib/internal/crypto/chacha20_poly1305.js | 31 +------ src/crypto/crypto_aes.cc | 85 ++++++----------- src/crypto/crypto_aes.h | 1 - src/crypto/crypto_chacha20_poly1305.cc | 91 +++---------------- src/crypto/crypto_chacha20_poly1305.h | 1 - ...pto-webcrypto-aes-decrypt-tag-too-small.js | 1 - ...-webcrypto-aead-decrypt-detached-buffer.js | 42 +++++++++ ...rypto-encrypt-decrypt-chacha20-poly1305.js | 2 +- 9 files changed, 91 insertions(+), 227 deletions(-) create mode 100644 test/parallel/test-webcrypto-aead-decrypt-detached-buffer.js diff --git a/lib/internal/crypto/aes.js b/lib/internal/crypto/aes.js index 0474060d394c99..c0765f75642189 100644 --- a/lib/internal/crypto/aes.js +++ b/lib/internal/crypto/aes.js @@ -1,12 +1,9 @@ 'use strict'; const { - ArrayBufferIsView, - ArrayBufferPrototypeSlice, ArrayFrom, ArrayPrototypePush, SafeSet, - TypedArrayPrototypeSlice, } = primordials; const { @@ -28,8 +25,6 @@ const { kKeyVariantAES_GCM_256, kKeyVariantAES_KW_256, kKeyVariantAES_OCB_256, - kWebCryptoCipherDecrypt, - kWebCryptoCipherEncrypt, } = internalBinding('crypto'); const { @@ -143,80 +138,33 @@ function asyncAesKwCipher(mode, key, data) { getVariant('AES-KW', key[kAlgorithm].length))); } -async function asyncAesGcmCipher(mode, key, data, algorithm) { +function asyncAesGcmCipher(mode, key, data, algorithm) { const { tagLength = 128 } = algorithm; - const tagByteLength = tagLength / 8; - let tag; - switch (mode) { - case kWebCryptoCipherDecrypt: { - const slice = ArrayBufferIsView(data) ? - TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice; - tag = slice(data, -tagByteLength); - - // Refs: https://www.w3.org/TR/WebCryptoAPI/#aes-gcm-operations - // - // > If *plaintext* has a length less than *tagLength* bits, then `throw` - // > an `OperationError`. - if (tagByteLength > tag.byteLength) { - throw lazyDOMException( - 'The provided data is too small.', - 'OperationError'); - } - data = slice(data, 0, -tagByteLength); - break; - } - case kWebCryptoCipherEncrypt: - tag = tagByteLength; - break; - } - - return await jobPromise(() => new AESCipherJob( + return jobPromise(() => new AESCipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], data, getVariant('AES-GCM', key[kAlgorithm].length), algorithm.iv, - tag, + tagByteLength, algorithm.additionalData)); } -async function asyncAesOcbCipher(mode, key, data, algorithm) { +function asyncAesOcbCipher(mode, key, data, algorithm) { const { tagLength = 128 } = algorithm; - const tagByteLength = tagLength / 8; - let tag; - switch (mode) { - case kWebCryptoCipherDecrypt: { - const slice = ArrayBufferIsView(data) ? - TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice; - tag = slice(data, -tagByteLength); - - // Similar to GCM, OCB requires the tag to be present for decryption - if (tagByteLength > tag.byteLength) { - throw lazyDOMException( - 'The provided data is too small.', - 'OperationError'); - } - data = slice(data, 0, -tagByteLength); - break; - } - case kWebCryptoCipherEncrypt: - tag = tagByteLength; - break; - } - - return await jobPromise(() => new AESCipherJob( + return jobPromise(() => new AESCipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], data, getVariant('AES-OCB', key.algorithm.length), algorithm.iv, - tag, + tagByteLength, algorithm.additionalData)); } diff --git a/lib/internal/crypto/chacha20_poly1305.js b/lib/internal/crypto/chacha20_poly1305.js index 0979d7aaddbb61..a2b7c1fb04fb89 100644 --- a/lib/internal/crypto/chacha20_poly1305.js +++ b/lib/internal/crypto/chacha20_poly1305.js @@ -1,19 +1,14 @@ 'use strict'; const { - ArrayBufferIsView, - ArrayBufferPrototypeSlice, ArrayFrom, SafeSet, - TypedArrayPrototypeSlice, } = primordials; const { ChaCha20Poly1305CipherJob, KeyObjectHandle, kCryptoJobAsync, - kWebCryptoCipherDecrypt, - kWebCryptoCipherEncrypt, } = internalBinding('crypto'); const { @@ -46,35 +41,13 @@ function validateKeyLength(length) { throw lazyDOMException('Invalid key length', 'DataError'); } -async function c20pCipher(mode, key, data, algorithm) { - let tag; - switch (mode) { - case kWebCryptoCipherDecrypt: { - const slice = ArrayBufferIsView(data) ? - TypedArrayPrototypeSlice : ArrayBufferPrototypeSlice; - - if (data.byteLength < 16) { - throw lazyDOMException( - 'The provided data is too small.', - 'OperationError'); - } - - tag = slice(data, -16); - data = slice(data, 0, -16); - break; - } - case kWebCryptoCipherEncrypt: - tag = 16; - break; - } - - return await jobPromise(() => new ChaCha20Poly1305CipherJob( +function c20pCipher(mode, key, data, algorithm) { + return jobPromise(() => new ChaCha20Poly1305CipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], data, algorithm.iv, - tag, algorithm.additionalData)); } diff --git a/src/crypto/crypto_aes.cc b/src/crypto/crypto_aes.cc index b5495e59737eb6..fa619696ffd5b2 100644 --- a/src/crypto/crypto_aes.cc +++ b/src/crypto/crypto_aes.cc @@ -76,24 +76,28 @@ WebCryptoCipherStatus AES_Cipher(Environment* env, } size_t tag_len = 0; + size_t data_len = in.size(); if (params.cipher.isGcmMode() || params.cipher.isOcbMode()) { + tag_len = params.length; switch (cipher_mode) { case kWebCryptoCipherDecrypt: { - // If in decrypt mode, the auth tag must be set in the params.tag. - CHECK(params.tag); + // In decrypt mode, the auth tag is appended to the end of the + // ciphertext. Split it off and set it on the cipher context. + if (data_len < tag_len) { + return WebCryptoCipherStatus::FAILED; + } + data_len -= tag_len; - // For OCB mode, we need to set the auth tag length before setting the - // tag if (params.cipher.isOcbMode()) { - if (!ctx.setAeadTagLength(params.tag.size())) { + if (!ctx.setAeadTagLength(tag_len)) { return WebCryptoCipherStatus::FAILED; } } ncrypto::Buffer buffer = { - .data = params.tag.data(), - .len = params.tag.size(), + .data = in.data() + data_len, + .len = tag_len, }; if (!ctx.setAeadTag(buffer)) { return WebCryptoCipherStatus::FAILED; @@ -101,14 +105,6 @@ WebCryptoCipherStatus AES_Cipher(Environment* env, break; } case kWebCryptoCipherEncrypt: { - // In encrypt mode, we grab the tag length here. We'll use it to - // ensure that that allocated buffer has enough room for both the - // final block and the auth tag. Unlike our other AES-GCM implementation - // in CipherBase, in WebCrypto, the auth tag is concatenated to the end - // of the generated ciphertext and returned in the same ArrayBuffer. - tag_len = params.length; - - // For OCB mode, we need to set the auth tag length if (params.cipher.isOcbMode()) { if (!ctx.setAeadTagLength(tag_len)) { return WebCryptoCipherStatus::FAILED; @@ -122,7 +118,7 @@ WebCryptoCipherStatus AES_Cipher(Environment* env, } size_t total = 0; - int buf_len = in.size() + ctx.getBlockSize() + tag_len; + int buf_len = data_len + ctx.getBlockSize() + (encrypt ? tag_len : 0); int out_len; ncrypto::Buffer buffer = { @@ -148,9 +144,9 @@ WebCryptoCipherStatus AES_Cipher(Environment* env, // Refs: https://github.com/nodejs/node/pull/38913#issuecomment-866505244 buffer = { .data = in.data(), - .len = in.size(), + .len = data_len, }; - if (in.empty()) { + if (data_len == 0) { out_len = 0; } else if (!ctx.update(buffer, ptr, &out_len)) { return WebCryptoCipherStatus::FAILED; @@ -381,42 +377,17 @@ bool ValidateCounter( return true; } -bool ValidateAuthTag( - Environment* env, - CryptoJobMode mode, - WebCryptoCipherMode cipher_mode, - Local value, - AESCipherConfig* params) { - switch (cipher_mode) { - case kWebCryptoCipherDecrypt: { - if (!IsAnyBufferSource(value)) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH(env); - return false; - } - ArrayBufferOrViewContents tag_contents(value); - if (!tag_contents.CheckSizeInt32()) [[unlikely]] { - THROW_ERR_OUT_OF_RANGE(env, "tagLength is too big"); - return false; - } - params->tag = mode == kCryptoJobAsync - ? tag_contents.ToCopy() - : tag_contents.ToByteSource(); - break; - } - case kWebCryptoCipherEncrypt: { - if (!value->IsUint32()) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH(env); - return false; - } - params->length = value.As()->Value(); - if (params->length > 128) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH(env); - return false; - } - break; - } - default: - UNREACHABLE(); +bool ValidateAuthTag(Environment* env, + Local value, + AESCipherConfig* params) { + if (!value->IsUint32()) { + THROW_ERR_CRYPTO_INVALID_TAG_LENGTH(env); + return false; + } + params->length = value.As()->Value(); + if (params->length > 128) { + THROW_ERR_CRYPTO_INVALID_TAG_LENGTH(env); + return false; } return true; } @@ -451,8 +422,7 @@ AESCipherConfig::AESCipherConfig(AESCipherConfig&& other) noexcept cipher(other.cipher), length(other.length), iv(std::move(other.iv)), - additional_data(std::move(other.additional_data)), - tag(std::move(other.tag)) {} + additional_data(std::move(other.additional_data)) {} AESCipherConfig& AESCipherConfig::operator=(AESCipherConfig&& other) noexcept { if (&other == this) return *this; @@ -466,7 +436,6 @@ void AESCipherConfig::MemoryInfo(MemoryTracker* tracker) const { if (mode == kCryptoJobAsync) { tracker->TrackFieldWithSize("iv", iv.size()); tracker->TrackFieldWithSize("additional_data", additional_data.size()); - tracker->TrackFieldWithSize("tag", tag.size()); } } @@ -510,7 +479,7 @@ Maybe AESCipherTraits::AdditionalConfig( return Nothing(); } } else if (params->cipher.isGcmMode() || params->cipher.isOcbMode()) { - if (!ValidateAuthTag(env, mode, cipher_mode, args[offset + 2], params) || + if (!ValidateAuthTag(env, args[offset + 2], params) || !ValidateAdditionalData(env, mode, args[offset + 3], params)) { return Nothing(); } diff --git a/src/crypto/crypto_aes.h b/src/crypto/crypto_aes.h index 401ef70a5eba9f..5627f9020bad54 100644 --- a/src/crypto/crypto_aes.h +++ b/src/crypto/crypto_aes.h @@ -52,7 +52,6 @@ struct AESCipherConfig final : public MemoryRetainer { size_t length; ByteSource iv; // Used for both iv or counter ByteSource additional_data; - ByteSource tag; // Used only for authenticated modes (GCM) AESCipherConfig() = default; diff --git a/src/crypto/crypto_chacha20_poly1305.cc b/src/crypto/crypto_chacha20_poly1305.cc index bfe904c49ad771..0fd3e0517317ca 100644 --- a/src/crypto/crypto_chacha20_poly1305.cc +++ b/src/crypto/crypto_chacha20_poly1305.cc @@ -54,63 +54,6 @@ bool ValidateIV(Environment* env, return true; } -bool ValidateAuthTag(Environment* env, - CryptoJobMode mode, - WebCryptoCipherMode cipher_mode, - Local value, - ChaCha20Poly1305CipherConfig* params) { - switch (cipher_mode) { - case kWebCryptoCipherDecrypt: { - if (!IsAnyBufferSource(value)) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH( - env, "Authentication tag must be a buffer"); - return false; - } - - ArrayBufferOrViewContents tag(value); - if (!tag.CheckSizeInt32()) [[unlikely]] { - THROW_ERR_OUT_OF_RANGE(env, "tag is too large"); - return false; - } - - if (tag.size() != kChaCha20Poly1305TagSize) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH( - env, "Invalid authentication tag length"); - return false; - } - - if (mode == kCryptoJobAsync) { - params->tag = tag.ToCopy(); - } else { - params->tag = tag.ToByteSource(); - } - break; - } - case kWebCryptoCipherEncrypt: { - // For encryption, the value should be the tag length (passed from - // JavaScript) We expect it to be the tag size constant for - // ChaCha20-Poly1305 - if (!value->IsUint32()) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH(env, "Tag length must be a number"); - return false; - } - - uint32_t tag_length = value.As()->Value(); - if (tag_length != kChaCha20Poly1305TagSize) { - THROW_ERR_CRYPTO_INVALID_TAG_LENGTH( - env, "Invalid tag length for ChaCha20-Poly1305"); - return false; - } - // Tag is generated during encryption, not provided - break; - } - default: - UNREACHABLE(); - } - - return true; -} - bool ValidateAdditionalData(Environment* env, CryptoJobMode mode, Local value, @@ -138,8 +81,7 @@ ChaCha20Poly1305CipherConfig::ChaCha20Poly1305CipherConfig( : mode(other.mode), cipher(other.cipher), iv(std::move(other.iv)), - additional_data(std::move(other.additional_data)), - tag(std::move(other.tag)) {} + additional_data(std::move(other.additional_data)) {} ChaCha20Poly1305CipherConfig& ChaCha20Poly1305CipherConfig::operator=( ChaCha20Poly1305CipherConfig&& other) noexcept { @@ -154,7 +96,6 @@ void ChaCha20Poly1305CipherConfig::MemoryInfo(MemoryTracker* tracker) const { if (mode == kCryptoJobAsync) { tracker->TrackFieldWithSize("iv", iv.size()); tracker->TrackFieldWithSize("additional_data", additional_data.size()); - tracker->TrackFieldWithSize("tag", tag.size()); } } @@ -179,17 +120,9 @@ Maybe ChaCha20Poly1305CipherTraits::AdditionalConfig( return Nothing(); } - // Authentication tag parameter (only for decryption) or tag length (for - // encryption) - if (static_cast(args.Length()) > offset + 1) { - if (!ValidateAuthTag(env, mode, cipher_mode, args[offset + 1], params)) { - return Nothing(); - } - } - // Additional authenticated data parameter (optional) - if (static_cast(args.Length()) > offset + 2) { - if (!ValidateAdditionalData(env, mode, args[offset + 2], params)) { + if (static_cast(args.Length()) > offset + 1) { + if (!ValidateAdditionalData(env, mode, args[offset + 1], params)) { return Nothing(); } } @@ -229,23 +162,25 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( return WebCryptoCipherStatus::FAILED; } - size_t tag_len = 0; + size_t tag_len = kChaCha20Poly1305TagSize; + size_t data_len = in.size(); switch (cipher_mode) { case kWebCryptoCipherDecrypt: { - if (params.tag.size() != kChaCha20Poly1305TagSize) { + if (data_len < tag_len) { return WebCryptoCipherStatus::FAILED; } + data_len -= tag_len; + if (!ctx.setAeadTag(ncrypto::Buffer{ - .data = params.tag.data(), - .len = params.tag.size(), + .data = in.data() + data_len, + .len = tag_len, })) { return WebCryptoCipherStatus::FAILED; } break; } case kWebCryptoCipherEncrypt: { - tag_len = kChaCha20Poly1305TagSize; break; } default: @@ -253,7 +188,7 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( } size_t total = 0; - int buf_len = in.size() + ctx.getBlockSize() + tag_len; + int buf_len = data_len + ctx.getBlockSize() + (encrypt ? tag_len : 0); int out_len; // Process additional authenticated data if present @@ -271,9 +206,9 @@ WebCryptoCipherStatus ChaCha20Poly1305CipherTraits::DoCipher( // Process the input data buffer = { .data = in.data(), - .len = in.size(), + .len = data_len, }; - if (in.empty()) { + if (data_len == 0) { if (!ctx.update({}, ptr, &out_len)) { return WebCryptoCipherStatus::FAILED; } diff --git a/src/crypto/crypto_chacha20_poly1305.h b/src/crypto/crypto_chacha20_poly1305.h index 5b4d5cde2c3929..f56b1a2e74a152 100644 --- a/src/crypto/crypto_chacha20_poly1305.h +++ b/src/crypto/crypto_chacha20_poly1305.h @@ -17,7 +17,6 @@ struct ChaCha20Poly1305CipherConfig final : public MemoryRetainer { ncrypto::Cipher cipher; ByteSource iv; ByteSource additional_data; - ByteSource tag; ChaCha20Poly1305CipherConfig() = default; diff --git a/test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js b/test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js index 589a2f91a17cc2..2f0612db2bc253 100644 --- a/test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js +++ b/test/parallel/test-crypto-webcrypto-aes-decrypt-tag-too-small.js @@ -24,6 +24,5 @@ subtle.importKey( }, k, new Uint8Array(0)); }, { name: 'OperationError', - message: /The provided data is too small/, }) ).then(common.mustCall()); diff --git a/test/parallel/test-webcrypto-aead-decrypt-detached-buffer.js b/test/parallel/test-webcrypto-aead-decrypt-detached-buffer.js new file mode 100644 index 00000000000000..a96e709095430f --- /dev/null +++ b/test/parallel/test-webcrypto-aead-decrypt-detached-buffer.js @@ -0,0 +1,42 @@ +'use strict'; + +const common = require('../common'); + +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { hasOpenSSL } = require('../common/crypto'); +const { subtle } = globalThis.crypto; + +async function test(algorithmName, keyLength, ivLength, format = 'raw') { + const key = await subtle.importKey( + format, + new Uint8Array(keyLength), + { name: algorithmName }, + false, + ['encrypt', 'decrypt'], + ); + + const data = new Uint8Array(32); + data.buffer.transfer(); + + await assert.rejects( + subtle.decrypt({ name: algorithmName, iv: new Uint8Array(ivLength) }, key, data), + { name: 'OperationError' }, + ); +} + +const tests = [ + test('AES-GCM', 32, 12), +]; + +if (hasOpenSSL(3)) { + tests.push(test('AES-OCB', 32, 12, 'raw-secret')); +} + +if (!process.features.openssl_is_boringssl) { + tests.push(test('ChaCha20-Poly1305', 32, 12, 'raw-secret')); +} + +Promise.all(tests).then(common.mustCall()); diff --git a/test/parallel/test-webcrypto-encrypt-decrypt-chacha20-poly1305.js b/test/parallel/test-webcrypto-encrypt-decrypt-chacha20-poly1305.js index aea9528f2463db..5362484288089d 100644 --- a/test/parallel/test-webcrypto-encrypt-decrypt-chacha20-poly1305.js +++ b/test/parallel/test-webcrypto-encrypt-decrypt-chacha20-poly1305.js @@ -189,7 +189,7 @@ async function testDecrypt({ keyBuffer, algorithm, result }) { const iv = globalThis.crypto.getRandomValues(new Uint8Array(12)); await assert.rejects( subtle.decrypt({ name: 'ChaCha20-Poly1305', iv }, secretKey, new Uint8Array(8)), - { name: 'OperationError', message: /The provided data is too small/ } + { name: 'OperationError' } ); // Test invalid tagLength values From 670c80893b0dbd68a801ce7e6d4a911a8ac41f88 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 11 Mar 2026 21:20:16 +0100 Subject: [PATCH 010/106] doc: add note (and caveat) for `mock.module` about customization hooks PR-URL: https://github.com/nodejs/node/pull/62075 Reviewed-By: Pietro Marchini --- doc/api/test.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/api/test.md b/doc/api/test.md index 6a987b36557099..9e43d3f802e014 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -2497,6 +2497,11 @@ Node.js builtin modules. Any references to the original module prior to mocking order to enable module mocking, Node.js must be started with the [`--experimental-test-module-mocks`][] command-line flag. +**Note**: [module customization hooks][] registered via the **synchronous** API effect resolution of +the `specifier` provided to `mock.module`. Customization hooks registered via the **asynchronous** +API are currently ignored (because the test runner's loader is synchronous, and node does not +support multi-chain / cross-chain loading). + The following example demonstrates how a mock is created for a module. ```js @@ -4244,6 +4249,7 @@ Can be used to abort test subtasks when the test has been aborted. [configuration files]: cli.md#--experimental-config-fileconfig [describe options]: #describename-options-fn [it options]: #testname-options-fn +[module customization hooks]: module.md#customization-hooks [running tests from the command line]: #running-tests-from-the-command-line [stream.compose]: stream.md#streamcomposestreams [subtests]: #subtests From 0000d2f01197a325485daf4cb2ae64e0eb134fd3 Mon Sep 17 00:00:00 2001 From: Ali Hassan <24819103+thisalihassan@users.noreply.github.com> Date: Thu, 12 Mar 2026 03:16:16 +0500 Subject: [PATCH 011/106] stream: replace bind with arrow function for onwrite callback PR-URL: https://github.com/nodejs/node/pull/62087 Reviewed-By: Mattias Buelens Reviewed-By: Benjamin Gruenbaum --- lib/internal/streams/writable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/streams/writable.js b/lib/internal/streams/writable.js index a9beecee156ee6..e934c38bbf9acc 100644 --- a/lib/internal/streams/writable.js +++ b/lib/internal/streams/writable.js @@ -347,7 +347,7 @@ function WritableState(options, stream, isDuplex) { this.corked = 0; // The callback that's passed to _write(chunk, cb). - this.onwrite = onwrite.bind(undefined, stream); + this.onwrite = (er) => onwrite(stream, er); // The amount that is being written when _write is called. this.writelen = 0; From 6c8fa42ba2ea308071a48d7f35c12b6cc5b3fcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9?= Date: Thu, 12 Mar 2026 02:02:47 +0000 Subject: [PATCH 012/106] typings: rationalise TypedArray types PR-URL: https://github.com/nodejs/node/pull/62174 Reviewed-By: Daijiro Wachi Reviewed-By: Yagiz Nizipli Reviewed-By: Zeyu "Alex" Yang --- typings/globals.d.ts | 14 +++++++++ typings/primordials.d.ts | 61 ++++++++++++---------------------------- 2 files changed, 32 insertions(+), 43 deletions(-) diff --git a/typings/globals.d.ts b/typings/globals.d.ts index 739f3d9a534026..ddd5885faa057f 100644 --- a/typings/globals.d.ts +++ b/typings/globals.d.ts @@ -87,6 +87,20 @@ declare global { | BigUint64Array | BigInt64Array; + type TypedArrayConstructor = + | typeof Uint8Array + | typeof Uint8ClampedArray + | typeof Uint16Array + | typeof Uint32Array + | typeof Int8Array + | typeof Int16Array + | typeof Int32Array + | typeof Float16Array + | typeof Float32Array + | typeof Float64Array + | typeof BigUint64Array + | typeof BigInt64Array; + namespace NodeJS { interface Global { internalBinding(binding: T): InternalBindingMap[T] diff --git a/typings/primordials.d.ts b/typings/primordials.d.ts index 204c12b0087f91..5437ac2736792a 100644 --- a/typings/primordials.d.ts +++ b/typings/primordials.d.ts @@ -19,7 +19,7 @@ type UncurryGetter = type UncurrySetter = O[K] extends infer V ? (self: T, value: V) => void : never; -type TypedArrayContentType = T extends { [k: number]: infer V } ? V : never; +type TypedArrayContentType = InstanceType[number]; /** * Primordials are a way to safely use globals without fear of global mutation @@ -472,14 +472,12 @@ declare namespace primordials { export const SyntaxErrorPrototype: typeof SyntaxError.prototype export import TypeError = globalThis.TypeError; export const TypeErrorPrototype: typeof TypeError.prototype - export function TypedArrayFrom( - constructor: new (length: number) => T, - source: - | Iterable> - | ArrayLike>, - ): T; - export function TypedArrayFrom( - constructor: new (length: number) => T, + export function TypedArrayFrom( + constructor: T, + source: Iterable> | ArrayLike>, + ): InstanceType + export function TypedArrayFrom( + constructor: T, source: Iterable | ArrayLike, mapfn: ( this: THIS_ARG, @@ -487,28 +485,17 @@ declare namespace primordials { index: number, ) => TypedArrayContentType, thisArg?: THIS_ARG, - ): T; - export function TypedArrayOf( - constructor: new (length: number) => T, - ...items: readonly TypedArrayContentType[] - ): T; - export function TypedArrayOfApply( - constructor: new (length: number) => T, + ): InstanceType; + export function TypedArrayOf( + constructor: T, + ...items: TypedArrayContentType[], + ): InstanceType; + export function TypedArrayOfApply( + constructor: T, items: readonly TypedArrayContentType[], - ): T; - export const TypedArray: TypedArray; - export const TypedArrayPrototype: - | typeof Uint8Array.prototype - | typeof Int8Array.prototype - | typeof Uint16Array.prototype - | typeof Int16Array.prototype - | typeof Uint32Array.prototype - | typeof Int32Array.prototype - | typeof Float32Array.prototype - | typeof Float64Array.prototype - | typeof BigInt64Array.prototype - | typeof BigUint64Array.prototype - | typeof Uint8ClampedArray.prototype; + ): InstanceType; + export const TypedArray: TypedArrayConstructor; + export const TypedArrayPrototype: TypedArrayConstructor["prototype"]; export const TypedArrayPrototypeGetBuffer: UncurryGetter; export const TypedArrayPrototypeGetByteLength: UncurryGetter; export const TypedArrayPrototypeGetByteOffset: UncurryGetter; @@ -519,19 +506,7 @@ declare namespace primordials { export function TypedArrayPrototypeSet(self: T, ...args: Parameters): ReturnType; export function TypedArrayPrototypeSubarray(self: T, ...args: Parameters): ReturnType; export function TypedArrayPrototypeSlice(self: T, ...args: Parameters): ReturnType; - export function TypedArrayPrototypeGetSymbolToStringTag(self: unknown): - | 'Int8Array' - | 'Int16Array' - | 'Int32Array' - | 'Uint8Array' - | 'Uint16Array' - | 'Uint32Array' - | 'Uint8ClampedArray' - | 'BigInt64Array' - | 'BigUint64Array' - | 'Float32Array' - | 'Float64Array' - | undefined; + export function TypedArrayPrototypeGetSymbolToStringTag(self: unknown): TypedArray[typeof Symbol.toStringTag] | undefined; export import URIError = globalThis.URIError; export const URIErrorPrototype: typeof URIError.prototype export import Uint16Array = globalThis.Uint16Array; From 47a2132269c8c7af661d112be0077d549eb8f3bc Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Thu, 12 Mar 2026 11:42:08 -0400 Subject: [PATCH 013/106] test: update WPT for WebCryptoAPI to 6a1c545d77 PR-URL: https://github.com/nodejs/node/pull/62187 Reviewed-By: Colin Ihrig Reviewed-By: Filip Skokan Reviewed-By: Antoine du Hamel --- test/fixtures/wpt/README.md | 2 +- .../digest/cshake.tentative.https.any.js | 41 +++- .../WebCryptoAPI/digest/digest.https.any.js | 24 +++ .../digest/sha3.tentative.https.any.js | 38 +++- .../wpt/WebCryptoAPI/encrypt_decrypt/aes.js | 126 +++++++++++ .../wpt/WebCryptoAPI/encrypt_decrypt/rsa.js | 179 ++++++++++++++-- .../wpt/WebCryptoAPI/sign_verify/ecdsa.js | 142 +++++++++++-- .../wpt/WebCryptoAPI/sign_verify/eddsa.js | 92 +++++++- .../wpt/WebCryptoAPI/sign_verify/hmac.js | 134 ++++++++++-- .../wpt/WebCryptoAPI/sign_verify/kmac.js | 148 ++++++++++++- .../wpt/WebCryptoAPI/sign_verify/mldsa.js | 200 ++++++++++++++++++ .../wpt/WebCryptoAPI/sign_verify/rsa.js | 134 ++++++++++-- .../wrapKey_unwrapKey.https.any.js | 6 +- test/fixtures/wpt/versions.json | 2 +- 14 files changed, 1187 insertions(+), 81 deletions(-) diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 34dadc7a702755..89f0cefdb6363e 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -34,7 +34,7 @@ Last update: - wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi - web-locks: https://github.com/web-platform-tests/wpt/tree/10a122a6bc/web-locks -- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/c9e955840a/WebCryptoAPI +- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/6a1c545d77/WebCryptoAPI - webidl: https://github.com/web-platform-tests/wpt/tree/63ca529a02/webidl - webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/2f96fa1996/webidl/ecmascript-binding/es-exceptions - webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/6495c91853/webmessaging/broadcastchannel diff --git a/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js b/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js index d5f790e42b4982..d0c23c09ada4a9 100644 --- a/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js +++ b/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js @@ -195,17 +195,52 @@ Object.keys(digestedData).forEach(function (alg) { promise_test(function (test) { var buffer = new Uint8Array(sourceData[size]); - return crypto.subtle + var promise = crypto.subtle .digest({ name: alg, length: length }, buffer) .then(function (result) { - // Alter the buffer after calling digest - buffer[0] = ~buffer[0]; assert_true( equalBuffers(result, digestedData[alg][length][size]), 'digest matches expected' ); }); + // Alter the buffer after calling digest + buffer[0] = ~buffer[0]; + return promise; }, alg + ' with ' + length + ' bit output and ' + size + ' source data and altered buffer after call'); + + promise_test(function (test) { + var buffer = new Uint8Array(sourceData[size]); + return crypto.subtle + .digest({ + get name() { + // Transfer the buffer while calling digest + buffer.buffer.transfer(); + return alg; + }, + length + }, buffer) + .then(function (result) { + assert_true( + equalBuffers(result, digestedData[alg][length].empty), + 'digest on transferred buffer should match result for empty buffer' + ); + }); + }, alg + ' with ' + length + ' bit output and ' + size + ' source data and transferred buffer during call'); + + promise_test(function (test) { + var buffer = new Uint8Array(sourceData[size]); + var promise = crypto.subtle + .digest({ name: alg, length: length }, buffer) + .then(function (result) { + assert_true( + equalBuffers(result, digestedData[alg][length][size]), + 'digest matches expected' + ); + }); + // Transfer the buffer after calling digest + buffer.buffer.transfer(); + return promise; + }, alg + ' with ' + length + ' bit output and ' + size + ' source data and transferred buffer after call'); } }); }); diff --git a/test/fixtures/wpt/WebCryptoAPI/digest/digest.https.any.js b/test/fixtures/wpt/WebCryptoAPI/digest/digest.https.any.js index e0c85f8f6b30e4..47bc220d44fb70 100644 --- a/test/fixtures/wpt/WebCryptoAPI/digest/digest.https.any.js +++ b/test/fixtures/wpt/WebCryptoAPI/digest/digest.https.any.js @@ -113,6 +113,30 @@ copiedBuffer[0] = 255 - copiedBuffer[0]; return promise; }, upCase + " with " + size + " source data and altered buffer after call"); + + promise_test(function(test) { + var copiedBuffer = copyBuffer(sourceData[size]); + copiedBuffer.buffer.transfer(); + return subtle.digest({name: upCase}, copiedBuffer) + .then(function(result) { + assert_true(equalBuffers(result, digestedData[alg].empty), "digest() on transferred buffer should yield result for empty buffer for " + alg + ":" + size); + }, function(err) { + assert_unreached("digest() threw an error for transferred buffer for " + alg + ":" + size + ": " + err.message); + }); + }, upCase + " with " + size + " source data and transferred buffer during call"); + + promise_test(function(test) { + var copiedBuffer = copyBuffer(sourceData[size]); + var promise = subtle.digest({name: upCase}, copiedBuffer) + .then(function(result) { + assert_true(equalBuffers(result, digestedData[alg][size]), "digest() yielded expected result for " + alg + ":" + size); + }, function(err) { + assert_unreached("digest() threw an error for " + alg + ":" + size + " - " + err.message); + }); + + copiedBuffer.buffer.transfer(); + return promise; + }, upCase + " with " + size + " source data and transferred buffer after call"); } }); }); diff --git a/test/fixtures/wpt/WebCryptoAPI/digest/sha3.tentative.https.any.js b/test/fixtures/wpt/WebCryptoAPI/digest/sha3.tentative.https.any.js index fc33608e07ab14..4ae99791b8c95f 100644 --- a/test/fixtures/wpt/WebCryptoAPI/digest/sha3.tentative.https.any.js +++ b/test/fixtures/wpt/WebCryptoAPI/digest/sha3.tentative.https.any.js @@ -132,15 +132,47 @@ Object.keys(sourceData).forEach(function (size) { promise_test(function (test) { var buffer = new Uint8Array(sourceData[size]); - return crypto.subtle.digest(alg, buffer).then(function (result) { - // Alter the buffer after calling digest - buffer[0] = ~buffer[0]; + var promise = crypto.subtle.digest(alg, buffer).then(function (result) { assert_true( equalBuffers(result, digestedData[alg][size]), 'digest matches expected' ); }); + // Alter the buffer after calling digest + buffer[0] = ~buffer[0]; + return promise; }, alg + ' with ' + size + ' source data and altered buffer after call'); + + promise_test(function (test) { + var buffer = new Uint8Array(sourceData[size]); + return crypto.subtle + .digest({ + get name() { + // Transfer the buffer while calling digest + buffer.buffer.transfer(); + return alg; + } + }, buffer) + .then(function (result) { + assert_true( + equalBuffers(result, digestedData[alg].empty), + 'digest on transferred buffer should match result for empty buffer' + ); + }); + }, alg + ' with ' + size + ' source data and transferred buffer during call'); + + promise_test(function (test) { + var buffer = new Uint8Array(sourceData[size]); + var promise = crypto.subtle.digest(alg, buffer).then(function (result) { + assert_true( + equalBuffers(result, digestedData[alg][size]), + 'digest matches expected' + ); + }); + // Transfer the buffer after calling digest + buffer.buffer.transfer(); + return promise; + }, alg + ' with ' + size + ' source data and transferred buffer after call'); } }); }); diff --git a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js index b157a94a0dc4fb..456f66423419c8 100644 --- a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js +++ b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/aes.js @@ -93,6 +93,67 @@ function run_test() { all_promises.push(promise); }); + // Check for encryption of an empty value if the buffer is transferred while calling encrypt. + passingVectors.forEach(function(vector) { + var plaintext = copyBuffer(vector.plaintext); + var promise = importVectorKey(vector, ["encrypt", "decrypt"]) + .then(function(vector) { + promise_test(function(test) { + var operation = subtle.encrypt({ + ...vector.algorithm, + get name() { + plaintext.buffer.transfer(); + return vector.algorithm.name; + } + }, vector.key, plaintext) + .then(function(result) { + var expectedLength = + ["AES-GCM", "AES-OCB"].includes(vector.algorithm.name) ? vector.algorithm.tagLength / 8 : + vector.algorithm.name === "AES-CBC" ? 16 : + 0; + assert_equals(result.byteLength, expectedLength, "Transferred plaintext yields an empty ciphertext"); + }, function(err) { + assert_unreached("encrypt error for test " + vector.name + ": " + err.message); + }); + return operation; + }, vector.name + " with transferred plaintext during call"); + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importKey failed for " + vector.name); + }, "importKey step: " + vector.name + " with transferred plaintext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful encryption even if the buffer is transferred after calling encrypt. + passingVectors.forEach(function(vector) { + var plaintext = copyBuffer(vector.plaintext); + var promise = importVectorKey(vector, ["encrypt", "decrypt"]) + .then(function(vector) { + promise_test(function(test) { + var operation = subtle.encrypt(vector.algorithm, vector.key, plaintext) + .then(function(result) { + assert_true(equalBuffers(result, vector.result), "Should return expected result"); + }, function(err) { + assert_unreached("encrypt error for test " + vector.name + ": " + err.message); + }); + plaintext.buffer.transfer(); + return operation; + }, vector.name + " with transferred plaintext after call"); + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importKey failed for " + vector.name); + }, "importKey step: " + vector.name + " with transferred plaintext after call"); + }); + + all_promises.push(promise); + }); + // Check for successful decryption. passingVectors.forEach(function(vector) { var promise = importVectorKey(vector, ["encrypt", "decrypt"]) @@ -174,6 +235,71 @@ function run_test() { all_promises.push(promise); }); + // Check for decryption when ciphertext is transferred while calling decrypt. + passingVectors.forEach(function(vector) { + var ciphertext = copyBuffer(vector.result); + var promise = importVectorKey(vector, ["encrypt", "decrypt"]) + .then(function(vector) { + promise_test(function(test) { + var operation = subtle.decrypt({ + ...vector.algorithm, + get name() { + ciphertext.buffer.transfer(); + return vector.algorithm.name; + } + }, vector.key, ciphertext) + .then(function(result) { + if (vector.algorithm.name === "AES-CTR") { + assert_equals(result.byteLength, 0, "Transferred ciphertext yields empty plaintext"); + } else { + assert_unreached("decrypt should not have succeeded for " + vector.name); + } + }, function(err) { + if (vector.algorithm.name === "AES-CTR") { + assert_unreached("decrypt error for test " + vector.name + ": " + err.message); + } else { + assert_equals(err.name, "OperationError", "Should throw an OperationError instead of " + err.message); + } + }); + return operation; + }, vector.name + " decryption with transferred ciphertext during call"); + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importKey failed for " + vector.name); + }, "importKey step for decryption: " + vector.name + " with transferred ciphertext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful decryption even if ciphertext is transferred after calling encrypt. + passingVectors.forEach(function(vector) { + var ciphertext = copyBuffer(vector.result); + var promise = importVectorKey(vector, ["encrypt", "decrypt"]) + .then(function(vector) { + promise_test(function(test) { + var operation = subtle.decrypt(vector.algorithm, vector.key, ciphertext) + .then(function(result) { + assert_true(equalBuffers(result, vector.plaintext), "Should return expected result"); + }, function(err) { + assert_unreached("decrypt error for test " + vector.name + ": " + err.message); + }); + ciphertext.buffer.transfer(); + return operation; + }, vector.name + " decryption with transferred ciphertext after call"); + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importKey failed for " + vector.name); + }, "importKey step for decryption: " + vector.name + " with transferred ciphertext after call"); + }); + + all_promises.push(promise); + }); + // Everything that succeeded should fail if no "encrypt" usage. passingVectors.forEach(function(vector) { // Don't want to overwrite key being used for success tests! diff --git a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js index 76c90809783205..6f585cbe1ffcef 100644 --- a/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js +++ b/test/fixtures/wpt/WebCryptoAPI/encrypt_decrypt/rsa.js @@ -25,7 +25,7 @@ function run_test() { .then(function(plaintext) { assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works")); }, function(err) { - assert_unreached("Decryption should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'"); }); }, vector.name + " decryption"); @@ -62,7 +62,7 @@ function run_test() { .then(function(plaintext) { assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works")); }, function(err) { - assert_unreached("Decryption should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; }, vector.name + " decryption with altered ciphertext during call"); @@ -78,7 +78,7 @@ function run_test() { all_promises.push(promise); }); - // Test decryption with an altered buffer + // Test decryption with an altered buffer after call passingVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) .then(function(vectors) { @@ -93,7 +93,7 @@ function run_test() { .then(function(plaintext) { assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works")); }, function(err) { - assert_unreached("Decryption should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'"); }); ciphertext[0] = 255 - ciphertext[0]; return operation; @@ -110,6 +110,75 @@ function run_test() { all_promises.push(promise); }); + // Test decryption with a transferred buffer during call + passingVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) + .then(function(vectors) { + // Get a one byte longer plaintext to encrypt + if (!("ciphertext" in vector)) { + return; + } + + promise_test(function(test) { + var ciphertext = copyBuffer(vector.ciphertext); + var operation = subtle.decrypt({ + ...vector.algorithm, + get name() { + ciphertext.buffer.transfer(); + return vector.algorithm.name; + } + }, vector.privateKey, ciphertext) + .then(function(plaintext) { + assert_unreached("Decryption should not have succeeded for " + vector.name); + }, function(err) { + assert_equals(err.name, "OperationError", "Should throw OperationError instead of " + err.message); + }); + return operation; + }, vector.name + " decryption with transferred ciphertext during call"); + + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " decryption with transferred ciphertext during call"); + }); + + all_promises.push(promise); + }); + + // Test decryption with a transferred buffer after call + passingVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) + .then(function(vectors) { + // Get a one byte longer plaintext to encrypt + if (!("ciphertext" in vector)) { + return; + } + + promise_test(function(test) { + var ciphertext = copyBuffer(vector.ciphertext); + var operation = subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext) + .then(function(plaintext) { + assert_true(equalBuffers(plaintext, vector.plaintext, "Decryption works")); + }, function(err) { + assert_unreached("Decryption should not throw error " + vector.name + ": '" + err.message + "'"); + }); + ciphertext.buffer.transfer(); + return operation; + }, vector.name + " decryption with transferred ciphertext after call"); + + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " decryption with transferred ciphertext after call"); + }); + + all_promises.push(promise); + }); + // Check for failures due to using publicKey to decrypt. passingVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) @@ -117,7 +186,7 @@ function run_test() { promise_test(function(test) { return subtle.decrypt(vector.algorithm, vector.publicKey, vector.ciphertext) .then(function(plaintext) { - assert_unreached("Should have thrown error for using publicKey to decrypt in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for using publicKey to decrypt in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message); }); @@ -145,7 +214,7 @@ function run_test() { promise_test(function(test) { return subtle.decrypt(vector.algorithm, vector.publicKey, vector.ciphertext) .then(function(plaintext) { - assert_unreached("Should have thrown error for no decrypt usage in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for no decrypt usage in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message); }); @@ -185,7 +254,7 @@ function run_test() { assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext"); return ciphertext; }, function(err) { - assert_unreached("decrypt error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'"); }); }) .then(function(priorCiphertext) { @@ -229,7 +298,7 @@ function run_test() { assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext"); return ciphertext; }, function(err) { - assert_unreached("decrypt error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'"); }); }) .then(function(priorCiphertext) { @@ -259,6 +328,92 @@ function run_test() { all_promises.push(promise); }); + // Check for encryption of an empty value if plaintext is transferred during call. + passingVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) + .then(function(vectors) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.encrypt({ + ...vector.algorithm, + get name() { + plaintext.buffer.transfer(); + return vector.algorithm.name; + } + }, vector.publicKey, plaintext) + .then(function(ciphertext) { + assert_equals(ciphertext.byteLength * 8, vector.privateKey.algorithm.modulusLength, "Ciphertext length matches modulus length"); + // Do we get an empty plaintext back via decrypt? + return subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext) + .then(function(result) { + assert_equals(result.byteLength, 0, "Decryption returns empty plaintext"); + return ciphertext; + }, function(err) { + assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'"); + }); + }, function(err) { + assert_unreached("encrypt error for test " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " with transferred plaintext during call"); + + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful encryption even if plaintext is transferred after call. + passingVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) + .then(function(vectors) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.encrypt(vector.algorithm, vector.publicKey, plaintext) + .then(function(ciphertext) { + assert_equals(ciphertext.byteLength * 8, vector.privateKey.algorithm.modulusLength, "Ciphertext length matches modulus length"); + // Can we get the original plaintext back via decrypt? + return subtle.decrypt(vector.algorithm, vector.privateKey, ciphertext) + .then(function(result) { + assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext"); + return ciphertext; + }, function(err) { + assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'"); + }); + }) + .then(function(priorCiphertext) { + // Will a second encrypt give us different ciphertext, as it should? + return subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext) + .then(function(ciphertext) { + assert_false(equalBuffers(priorCiphertext, ciphertext), "Two encrypts give different results") + }, function(err) { + assert_unreached("second time encrypt error for test " + vector.name + ": '" + err.message + "'"); + }); + }, function(err) { + assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'"); + }); + + plaintext.buffer.transfer(); + return operation; + }, vector.name + " with transferred plaintext after call"); + + }, function(err) { + // We need a failed test if the importVectorKey operation fails, so + // we know we never tested encryption + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext after call"); + }); + + all_promises.push(promise); + }); + // Check for successful encryption. passingVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["encrypt"], ["decrypt"]) @@ -274,7 +429,7 @@ function run_test() { assert_true(equalBuffers(result, vector.plaintext), "Round trip returns original plaintext"); return ciphertext; }, function(err) { - assert_unreached("decrypt error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("decrypt error for test " + vector.name + ": '" + err.message + "'"); }); }) .then(function(priorCiphertext) { @@ -312,7 +467,7 @@ function run_test() { promise_test(function(test) { return subtle.encrypt(vector.algorithm, vector.publicKey, plaintext) .then(function(ciphertext) { - assert_unreached("Should have thrown error for too long plaintext in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for too long plaintext in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "OperationError", "Should throw OperationError instead of " + err.message); }); @@ -337,7 +492,7 @@ function run_test() { promise_test(function(test) { return subtle.encrypt(vector.algorithm, vector.privateKey, vector.plaintext) .then(function(ciphertext) { - assert_unreached("Should have thrown error for using privateKey to encrypt in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for using privateKey to encrypt in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message); }); @@ -365,7 +520,7 @@ function run_test() { promise_test(function(test) { return subtle.encrypt(vector.algorithm, vector.publicKey, vector.plaintext) .then(function(ciphertext) { - assert_unreached("Should have thrown error for no encrypt usage in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for no encrypt usage in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of " + err.message); }); diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/ecdsa.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/ecdsa.js index 9b47868fe32bfb..b2e0bf606b5fee 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/ecdsa.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/ecdsa.js @@ -22,7 +22,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -57,7 +57,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -82,7 +82,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); signature[0] = 255 - signature[0]; @@ -97,6 +97,63 @@ function run_test() { all_promises.push(promise); }); + // Test verification with a transferred buffer during call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var algorithm = { + get name() { + signature.buffer.transfer(); + return vector.algorithmName; + }, + hash: vector.hashName + }; + var operation = subtle.verify(algorithm, vector.publicKey, signature, vector.plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " verification with transferred signature during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature during call"); + }); + + all_promises.push(promise); + }); + + // Test verification with a transferred buffer after call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + var algorithm = {name: vector.algorithmName, hash: vector.hashName}; + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var operation = subtle.verify(algorithm, vector.publicKey, signature, vector.plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + signature.buffer.transfer(); + return operation; + }, vector.name + " verification with transferred signature after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature after call"); + }); + + all_promises.push(promise); + }); + // Check for successful verification even if plaintext is altered during call. testVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["verify"], ["sign"]) @@ -115,7 +172,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -140,7 +197,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); plaintext[0] = 255 - plaintext[0]; @@ -155,6 +212,63 @@ function run_test() { all_promises.push(promise); }); + // Check for failed verification if plaintext is transferred during call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var algorithm = { + get name() { + plaintext.buffer.transfer(); + return vector.algorithmName; + }, + hash: vector.hashName + }; + var operation = subtle.verify(algorithm, vector.publicKey, vector.signature, plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " with transferred plaintext during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful verification even if plaintext is transferred after call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + var algorithm = {name: vector.algorithmName, hash: vector.hashName}; + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.verify(algorithm, vector.publicKey, vector.signature, plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + plaintext.buffer.transfer(); + return operation; + }, vector.name + " with transferred plaintext after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext after call"); + }); + + all_promises.push(promise); + }); + // Check for failures due to using privateKey to verify. testVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["verify"], ["sign"]) @@ -163,7 +277,7 @@ function run_test() { promise_test(function(test) { return subtle.verify(algorithm, vector.privateKey, vector.signature, vector.plaintext) .then(function(plaintext) { - assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -186,7 +300,7 @@ function run_test() { promise_test(function(test) { return subtle.sign(algorithm, vector.publicKey, vector.plaintext) .then(function(signature) { - assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -210,7 +324,7 @@ function run_test() { promise_test(function(test) { return subtle.verify(algorithm, vector.publicKey, vector.signature, vector.plaintext) .then(function(plaintext) { - assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -238,7 +352,7 @@ function run_test() { assert_true(is_verified, "Round trip verification works"); return signature; }, function(err) { - assert_unreached("verify error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("verify error for test " + vector.name + ": '" + err.message + "'"); }); }, function(err) { assert_unreached("sign error for test " + vector.name + ": '" + err.message + "'"); @@ -338,7 +452,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -369,7 +483,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -426,7 +540,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -455,7 +569,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -482,7 +596,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature unexpectedly verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa.js index 4bf1887b2ae9bb..5ff6f21150c272 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/eddsa.js @@ -18,7 +18,7 @@ function run_test(algorithmName) { isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data) } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_true(isVerified, "Signature verified"); }, vector.name + " verification"); @@ -39,7 +39,7 @@ function run_test(algorithmName) { }, key, signature, vector.data); } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_true(isVerified, "Signature verified"); }, vector.name + " verification with altered signature during call"); @@ -57,11 +57,48 @@ function run_test(algorithmName) { ]); } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_true(isVerified, "Signature verified"); }, vector.name + " verification with altered signature after call"); + // Test verification with a transferred buffer during call + promise_test(async() => { + let isVerified = false; + let key; + try { + key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]); + var signature = copyBuffer(vector.signature); + isVerified = await subtle.verify({ + get name() { + signature.buffer.transfer(); + return vector.algorithmName; + } + }, key, signature, vector.data); + } catch (err) { + assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }; + assert_false(isVerified, "Signature is NOT verified"); + }, vector.name + " verification with transferred signature during call"); + + // Test verification with a transferred buffer after call + promise_test(async() => { + let isVerified = false; + let key; + try { + key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]); + var signature = copyBuffer(vector.signature); + var operation = subtle.verify(algorithm, key, signature, vector.data); + signature.buffer.transfer(); + isVerified = await operation; + } catch (err) { + assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }; + assert_true(isVerified, "Signature verified"); + }, vector.name + " verification with transferred signature after call"); + // Check for successful verification even if data is altered during call. promise_test(async() => { let isVerified = false; @@ -78,7 +115,7 @@ function run_test(algorithmName) { }, key, vector.signature, data); } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_true(isVerified, "Signature verified"); }, vector.name + " with altered data during call"); @@ -96,11 +133,48 @@ function run_test(algorithmName) { ]); } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_true(isVerified, "Signature verified"); }, vector.name + " with altered data after call"); + // Check for failed verification if data is transferred during call. + promise_test(async() => { + let isVerified = false; + let key; + try { + key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]); + var data = copyBuffer(vector.data); + isVerified = await subtle.verify({ + get name() { + data.buffer.transfer(); + return vector.algorithmName; + } + }, key, vector.signature, data); + } catch (err) { + assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }; + assert_false(isVerified, "Signature is NOT verified"); + }, vector.name + " with transferred data during call"); + + // Check for successful verification even if data is transferred after call. + promise_test(async() => { + let isVerified = false; + let key; + try { + key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]); + var data = copyBuffer(vector.data); + var operation = subtle.verify(algorithm, key, vector.signature, data); + data.buffer.transfer(); + isVerified = await operation; + } catch (err) { + assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }; + assert_true(isVerified, "Signature verified"); + }, vector.name + " with transferred data after call"); + // Check for failures due to using privateKey to verify. promise_test(async() => { let isVerified = false; @@ -165,7 +239,7 @@ function run_test(algorithmName) { } catch (err) { assert_false(publicKey === undefined || privateKey === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); assert_false(signature === undefined, "sign error for test " + vector.name + ": '" + err.message + "'"); - assert_unreached("verify error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("verify error for test " + vector.name + ": '" + err.message + "'"); }; assert_true(isVerified, "Round trip verification works"); }, vector.name + " round trip"); @@ -214,7 +288,7 @@ function run_test(algorithmName) { isVerified = await subtle.verify(algorithm, key, signature, vector.data) } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_false(isVerified, "Signature verified"); }, vector.name + " verification failure due to altered signature"); @@ -229,7 +303,7 @@ function run_test(algorithmName) { isVerified = await subtle.verify(algorithm, key, signature, vector.data) } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_false(isVerified, "Signature verified"); }, vector.name + " verification failure due to shortened signature"); @@ -245,7 +319,7 @@ function run_test(algorithmName) { isVerified = await subtle.verify(algorithm, key, vector.signature, data) } catch (err) { assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''"); - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }; assert_false(isVerified, "Signature verified"); }, vector.name + " verification failure due to altered data"); diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/hmac.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/hmac.js index dff8c994d83de0..8a099f4ce9377a 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/hmac.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/hmac.js @@ -20,7 +20,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -45,16 +45,16 @@ function run_test() { var signature = copyBuffer(vector.signature); signature[0] = 255 - signature[0]; var operation = subtle.verify({ - hash: vector.hash, get name() { signature[0] = vector.signature[0]; return "HMAC"; - } + }, + hash: vector.hash }, vector.key, signature, vector.plaintext) .then(function(is_verified) { assert_true(is_verified, "Signature is not verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -78,7 +78,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature is not verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); signature[0] = 255 - signature[0]; @@ -93,6 +93,61 @@ function run_test() { all_promises.push(promise); }); + // Test verification with a transferred buffer during call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var operation = subtle.verify({ + get name() { + signature.buffer.transfer(); + return "HMAC"; + }, + hash: vector.hash + }, vector.key, signature, vector.plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " verification with transferred signature during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature during call"); + }); + + all_promises.push(promise); + }); + + // Test verification with a transferred buffer after call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var operation = subtle.verify({name: "HMAC", hash: vector.hash}, vector.key, signature, vector.plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature is not verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + signature.buffer.transfer(); + return operation; + }, vector.name + " verification with transferred signature after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature after call"); + }); + + all_promises.push(promise); + }); + // Check for successful verification even if plaintext is altered during call. testVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["verify", "sign"]) @@ -110,7 +165,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -134,7 +189,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); plaintext[0] = 255 - plaintext[0]; @@ -149,6 +204,61 @@ function run_test() { all_promises.push(promise); }); + // Check for failed verification if plaintext is transferred during call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.verify({ + get name() { + plaintext.buffer.transfer(); + return "HMAC"; + }, + hash: vector.hash + }, vector.key, vector.signature, plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " with transferred plaintext during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful verification even if plaintext is transferred after call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.verify({name: "HMAC", hash: vector.hash}, vector.key, vector.signature, plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + plaintext.buffer.transfer(); + return operation; + }, vector.name + " with transferred plaintext after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext after call"); + }); + + all_promises.push(promise); + }); + // Check for failures due to no "verify" usage. testVectors.forEach(function(originalVector) { var vector = Object.assign({}, originalVector); @@ -158,7 +268,7 @@ function run_test() { promise_test(function(test) { return subtle.verify({name: "HMAC", hash: vector.hash}, vector.key, vector.signature, vector.plaintext) .then(function(plaintext) { - assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -186,7 +296,7 @@ function run_test() { assert_true(is_verified, "Round trip verifies"); return signature; }, function(err) { - assert_unreached("verify error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("verify error for test " + vector.name + ": '" + err.message + "'"); }); }); }, vector.name + " round trip"); @@ -281,7 +391,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -309,7 +419,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -336,7 +446,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js index 57c9dc6f34790a..f3cc9b4cd1dbfd 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js @@ -23,7 +23,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -61,7 +61,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature is not verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -89,7 +89,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature is not verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); signature[0] = 255 - signature[0]; @@ -104,6 +104,69 @@ function run_test() { all_promises.push(promise); }); + // Test verification with a transferred buffer during call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var algorithmParams = { + get name() { + signature.buffer.transfer(); + return vector.algorithm; + }, + length: vector.length + }; + if (vector.customization !== undefined) { + algorithmParams.customization = vector.customization; + } + var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " verification with transferred signature during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature during call"); + }); + + all_promises.push(promise); + }); + + // Test verification with a transferred buffer after call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var algorithmParams = {name: vector.algorithm, length: vector.length}; + if (vector.customization !== undefined) { + algorithmParams.customization = vector.customization; + } + var operation = subtle.verify(algorithmParams, vector.key, signature, vector.plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature is not verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + signature.buffer.transfer(); + return operation; + }, vector.name + " verification with transferred signature after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature after call"); + }); + + all_promises.push(promise); + }); + // Check for successful verification even if plaintext is altered during call. testVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["verify", "sign"]) @@ -125,7 +188,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -153,7 +216,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); plaintext[0] = 255 - plaintext[0]; @@ -168,6 +231,69 @@ function run_test() { all_promises.push(promise); }); + // Check for failed verification if plaintext is transferred during call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var algorithmParams = { + get name() { + plaintext.buffer.transfer(); + return vector.algorithm; + }, + length: vector.length + }; + if (vector.customization !== undefined) { + algorithmParams.customization = vector.customization; + } + var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " with transferred plaintext during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful verification even if plaintext is transferred after call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify", "sign"]) + .then(function(vector) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var algorithmParams = {name: vector.algorithm, length: vector.length}; + if (vector.customization !== undefined) { + algorithmParams.customization = vector.customization; + } + var operation = subtle.verify(algorithmParams, vector.key, vector.signature, plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + plaintext.buffer.transfer(); + return operation; + }, vector.name + " with transferred plaintext after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext after call"); + }); + + all_promises.push(promise); + }); + // Check for failures due to no "verify" usage. testVectors.forEach(function(originalVector) { var vector = Object.assign({}, originalVector); @@ -181,7 +307,7 @@ function run_test() { } return subtle.verify(algorithmParams, vector.key, vector.signature, vector.plaintext) .then(function(plaintext) { - assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -213,7 +339,7 @@ function run_test() { assert_true(is_verified, "Round trip verifies"); return signature; }, function(err) { - assert_unreached("verify error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("verify error for test " + vector.name + ": '" + err.message + "'"); }); }); }, vector.name + " round trip"); @@ -320,7 +446,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -352,7 +478,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -383,7 +509,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -414,7 +540,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature is NOT verified with wrong length"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/mldsa.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/mldsa.js index 88143a33879ed7..9c654685c74f31 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/mldsa.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/mldsa.js @@ -156,6 +156,106 @@ function run_test() { all_promises.push(promise); }); + // Test verification with a transferred buffer during call + testVectors.forEach(function (vector) { + var promise = importVectorKeys(vector, ['verify'], ['sign']).then( + function (vectors) { + promise_test(function (test) { + var signature = copyBuffer(vector.signature); + var operation = subtle + .verify( + { + get name() { + signature.buffer.transfer(); + return vector.algorithmName; + }, + }, + vector.publicKey, + signature, + vector.data + ) + .then( + function (is_verified) { + assert_false(is_verified, 'Signature is NOT verified'); + }, + function (err) { + assert_unreached( + 'Verification should not throw error ' + + vector.name + + ': ' + + err.message + + "'" + ); + } + ); + + return operation; + }, vector.name + ' verification with transferred signature during call'); + }, + function (err) { + promise_test(function (test) { + assert_unreached( + 'importVectorKeys failed for ' + + vector.name + + ". Message: ''" + + err.message + + "''" + ); + }, 'importVectorKeys step: ' + + vector.name + + ' verification with transferred signature during call'); + } + ); + + all_promises.push(promise); + }); + + // Test verification with a transferred buffer after call + testVectors.forEach(function (vector) { + var promise = importVectorKeys(vector, ['verify'], ['sign']).then( + function (vectors) { + var algorithm = vector.algorithmName; + promise_test(function (test) { + var signature = copyBuffer(vector.signature); + var operation = subtle + .verify(algorithm, vector.publicKey, signature, vector.data) + .then( + function (is_verified) { + assert_true(is_verified, 'Signature verified'); + }, + function (err) { + assert_unreached( + 'Verification should not throw error ' + + vector.name + + ': ' + + err.message + + "'" + ); + } + ); + + signature.buffer.transfer(); + return operation; + }, vector.name + ' verification with transferred signature after call'); + }, + function (err) { + promise_test(function (test) { + assert_unreached( + 'importVectorKeys failed for ' + + vector.name + + ". Message: ''" + + err.message + + "''" + ); + }, 'importVectorKeys step: ' + + vector.name + + ' verification with transferred signature after call'); + } + ); + + all_promises.push(promise); + }); + // Check for successful verification even if plaintext is altered during call. testVectors.forEach(function (vector) { var promise = importVectorKeys(vector, ['verify'], ['sign']).then( @@ -257,6 +357,106 @@ function run_test() { all_promises.push(promise); }); + // Check for failed verification if plaintext is transferred during call. + testVectors.forEach(function (vector) { + var promise = importVectorKeys(vector, ['verify'], ['sign']).then( + function (vectors) { + promise_test(function (test) { + var plaintext = copyBuffer(vector.data); + var operation = subtle + .verify( + { + get name() { + plaintext.buffer.transfer(); + return vector.algorithmName; + }, + }, + vector.publicKey, + vector.signature, + plaintext + ) + .then( + function (is_verified) { + assert_false(is_verified, 'Signature is NOT verified'); + }, + function (err) { + assert_unreached( + 'Verification should not throw error ' + + vector.name + + ': ' + + err.message + + "'" + ); + } + ); + + return operation; + }, vector.name + ' with transferred plaintext during call'); + }, + function (err) { + promise_test(function (test) { + assert_unreached( + 'importVectorKeys failed for ' + + vector.name + + ". Message: ''" + + err.message + + "''" + ); + }, 'importVectorKeys step: ' + + vector.name + + ' with transferred plaintext during call'); + } + ); + + all_promises.push(promise); + }); + + // Check for successful verification even if plaintext is transferred after call. + testVectors.forEach(function (vector) { + var promise = importVectorKeys(vector, ['verify'], ['sign']).then( + function (vectors) { + var algorithm = vector.algorithmName; + promise_test(function (test) { + var plaintext = copyBuffer(vector.data); + var operation = subtle + .verify(algorithm, vector.publicKey, vector.signature, plaintext) + .then( + function (is_verified) { + assert_true(is_verified, 'Signature verified'); + }, + function (err) { + assert_unreached( + 'Verification should not throw error ' + + vector.name + + ': ' + + err.message + + "'" + ); + } + ); + + plaintext.buffer.transfer(); + return operation; + }, vector.name + ' with transferred plaintext after call'); + }, + function (err) { + promise_test(function (test) { + assert_unreached( + 'importVectorKeys failed for ' + + vector.name + + ". Message: ''" + + err.message + + "''" + ); + }, 'importVectorKeys step: ' + + vector.name + + ' with transferred plaintext after call'); + } + ); + + all_promises.push(promise); + }); + // Check for failures due to using privateKey to verify. testVectors.forEach(function (vector) { var promise = importVectorKeys(vector, ['verify'], ['sign']).then( diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/rsa.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/rsa.js index f808714cfb11d4..09c7ceb7675107 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/rsa.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/rsa.js @@ -20,7 +20,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -54,7 +54,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -78,7 +78,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); signature[0] = 255 - signature[0]; @@ -93,6 +93,61 @@ function run_test() { all_promises.push(promise); }); + // Test verification with a transferred buffer during call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var operation = subtle.verify({ + ...vector.algorithm, + get name() { + signature.buffer.transfer(); + return vector.algorithm.name; + } + }, vector.publicKey, signature, vector.plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " verification with transferred signature during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature during call"); + }); + + all_promises.push(promise); + }); + + // Test verification with a transferred buffer after call + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + promise_test(function(test) { + var signature = copyBuffer(vector.signature); + var operation = subtle.verify(vector.algorithm, vector.publicKey, signature, vector.plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + signature.buffer.transfer(); + return operation; + }, vector.name + " verification with transferred signature after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " verification with transferred signature after call"); + }); + + all_promises.push(promise); + }); + // Check for successful verification even if plaintext is altered during call. testVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["verify"], ["sign"]) @@ -110,7 +165,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -134,7 +189,7 @@ function run_test() { .then(function(is_verified) { assert_true(is_verified, "Signature verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); plaintext[0] = 255 - plaintext[0]; @@ -149,6 +204,61 @@ function run_test() { all_promises.push(promise); }); + // Check for failed verification if plaintext is transferred during call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.verify({ + ...vector.algorithm, + get name() { + plaintext.buffer.transfer(); + return vector.algorithm.name; + } + }, vector.publicKey, vector.signature, plaintext) + .then(function(is_verified) { + assert_false(is_verified, "Signature is NOT verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + return operation; + }, vector.name + " with transferred plaintext during call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext during call"); + }); + + all_promises.push(promise); + }); + + // Check for successful verification even if plaintext is transferred after call. + testVectors.forEach(function(vector) { + var promise = importVectorKeys(vector, ["verify"], ["sign"]) + .then(function(vectors) { + promise_test(function(test) { + var plaintext = copyBuffer(vector.plaintext); + var operation = subtle.verify(vector.algorithm, vector.publicKey, vector.signature, plaintext) + .then(function(is_verified) { + assert_true(is_verified, "Signature verified"); + }, function(err) { + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); + }); + + plaintext.buffer.transfer(); + return operation; + }, vector.name + " with transferred plaintext after call"); + }, function(err) { + promise_test(function(test) { + assert_unreached("importVectorKeys failed for " + vector.name + ". Message: ''" + err.message + "''"); + }, "importVectorKeys step: " + vector.name + " with transferred plaintext after call"); + }); + + all_promises.push(promise); + }); + // Check for failures due to using privateKey to verify. testVectors.forEach(function(vector) { var promise = importVectorKeys(vector, ["verify"], ["sign"]) @@ -156,7 +266,7 @@ function run_test() { promise_test(function(test) { return subtle.verify(vector.algorithm, vector.privateKey, vector.signature, vector.plaintext) .then(function(plaintext) { - assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -178,7 +288,7 @@ function run_test() { promise_test(function(test) { return subtle.sign(vector.algorithm, vector.publicKey, vector.plaintext) .then(function(signature) { - assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -201,7 +311,7 @@ function run_test() { promise_test(function(test) { return subtle.verify(vector.algorithm, vector.publicKey, vector.signature, vector.plaintext) .then(function(plaintext) { - assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": " + err.message + "'"); + assert_unreached("Should have thrown error for no verify usage in " + vector.name + ": '" + err.message + "'"); }, function(err) { assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'"); }); @@ -234,7 +344,7 @@ function run_test() { assert_true(is_verified, "Round trip verifies"); return signature; }, function(err) { - assert_unreached("verify error for test " + vector.name + ": " + err.message + "'"); + assert_unreached("verify error for test " + vector.name + ": '" + err.message + "'"); }); }) .then(function(priorSignature) { @@ -351,7 +461,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -379,7 +489,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; @@ -408,7 +518,7 @@ function run_test() { .then(function(is_verified) { assert_false(is_verified, "Signature NOT verified"); }, function(err) { - assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'"); + assert_unreached("Verification should not throw error " + vector.name + ": '" + err.message + "'"); }); return operation; diff --git a/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/wrapKey_unwrapKey.https.any.js b/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/wrapKey_unwrapKey.https.any.js index e40b4b6d35f794..880f7d650964ae 100644 --- a/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/wrapKey_unwrapKey.https.any.js +++ b/test/fixtures/wpt/WebCryptoAPI/wrapKey_unwrapKey/wrapKey_unwrapKey.https.any.js @@ -75,7 +75,7 @@ var wrapper = wrappers[wrapperParam.name]; keysToWrapParameters.filter((param) => Object.keys(keys).includes(param.algorithm.name)).forEach(function(toWrapParam) { var keyData = keys[toWrapParam.algorithm.name]; - ["raw", "spki", "pkcs8"].filter((fmt) => Object.keys(keyData).includes(fmt)).forEach(function(keyDataFormat) { + ["raw", "raw-secret", "spki", "pkcs8"].filter((fmt) => Object.keys(keyData).includes(fmt)).forEach(function(keyDataFormat) { var toWrap = keyData[keyDataFormat]; [keyDataFormat, "jwk"].forEach(function(format) { if (wrappingIsPossible(toWrap.originalExport[format], wrapper.parameters.name)) { @@ -114,7 +114,7 @@ })); } else if (params.name === "ChaCha20-Poly1305") { var algorithm = {name: params.name}; - promises.push(subtle.importKey("raw", wrappingKeyData["SYMMETRIC256"].raw, algorithm, true, ["wrapKey", "unwrapKey"]) + promises.push(subtle.importKey("raw-secret", wrappingKeyData["SYMMETRIC256"].raw, algorithm, true, ["wrapKey", "unwrapKey"]) .then(function(key) { wrappers[params.name] = {wrappingKey: key, unwrappingKey: key, parameters: params}; })); @@ -165,7 +165,7 @@ promises.push(importAndExport("pkcs8", keyData.pkcs8, params.algorithm, params.privateUsages, "private key ")); } else if (params.algorithm.name === "ChaCha20-Poly1305") { keys[params.algorithm.name] = {}; - promises.push(importAndExport("raw", toWrapKeyData["SYMMETRIC256"].raw, params.algorithm, params.usages, "")); + promises.push(importAndExport("raw-secret", toWrapKeyData["SYMMETRIC256"].raw, params.algorithm, params.usages, "")); } else { keys[params.algorithm.name] = {}; promises.push(importAndExport("raw", toWrapKeyData["SYMMETRIC128"].raw, params.algorithm, params.usages, "")); diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index a3b6c290982f88..ba7488a89a20b9 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -96,7 +96,7 @@ "path": "web-locks" }, "WebCryptoAPI": { - "commit": "c9e955840a21be6e492225a4a53fc4828d8933b9", + "commit": "6a1c545d778f115c84a1c27c25484afd442b89d8", "path": "WebCryptoAPI" }, "webidl": { From f85b9d9fa82094f3fa0cac3fd1baceb438eab057 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 12 Mar 2026 17:35:31 +0100 Subject: [PATCH 014/106] repl: add customizable error handling Whether or not an exception should be handled when it was thrown in the REPL's context but the REPL is already closed is something that will depend on the details of the specific REPL instance's use case. Adding this option lets the REPL's creator control the details of this behavior. This resolves a TODO recently added in bd3cba5633e8a36. PR-URL: https://github.com/nodejs/node/pull/62188 Reviewed-By: Colin Ihrig Reviewed-By: Chemi Atlow --- doc/api/repl.md | 14 ++++ lib/repl.js | 25 ++++-- test/parallel/test-repl-user-error-handler.js | 84 +++++++++++++++++++ 3 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 test/parallel/test-repl-user-error-handler.js diff --git a/doc/api/repl.md b/doc/api/repl.md index 0ebd5ca4e6f465..c26b2a56dc8ad5 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -709,6 +709,9 @@ npx codemod@latest @nodejs/repl-builtin-modules + +These channels are emitted for each [`locks.request()`][] call. See +[`worker_threads.locks`][] for details on Web Locks. + +##### Event: `'locks.request.start'` + +* `name` {string} The name of the requested lock resource. +* `mode` {string} The lock mode: `'exclusive'` or `'shared'`. + +Emitted when a lock request is initiated, before the lock is granted. + +##### Event: `'locks.request.grant'` + +* `name` {string} The name of the requested lock resource. +* `mode` {string} The lock mode: `'exclusive'` or `'shared'`. + +Emitted when a lock is successfully granted and the callback is about to run. + +##### Event: `'locks.request.miss'` + +* `name` {string} The name of the requested lock resource. +* `mode` {string} The lock mode: `'exclusive'` or `'shared'`. + +Emitted when `ifAvailable` is `true` and the lock is not immediately available, +and the request callback is invoked with `null` instead of a `Lock` object. + +##### Event: `'locks.request.end'` + +* `name` {string} The name of the requested lock resource. +* `mode` {string} The lock mode: `'exclusive'` or `'shared'`. +* `steal` {boolean} Whether the request uses steal semantics. +* `ifAvailable` {boolean} Whether the request uses ifAvailable semantics. +* `error` {Error|undefined} The error thrown by the callback, if any. + +Emitted when a lock request has finished, whether the callback succeeded, +threw an error, or the lock was stolen. + #### Worker Thread > Stability: 1 - Experimental @@ -1476,7 +1520,9 @@ Emitted when a new thread is created. [`diagnostics_channel.tracingChannel()`]: #diagnostics_channeltracingchannelnameorchannels [`end` event]: #endevent [`error` event]: #errorevent +[`locks.request()`]: worker_threads.md#locksrequestname-options-callback [`net.Server.listen()`]: net.md#serverlisten [`process.execve()`]: process.md#processexecvefile-args-env [`start` event]: #startevent +[`worker_threads.locks`]: worker_threads.md#worker_threadslocks [context loss]: async_context.md#troubleshooting-context-loss diff --git a/lib/internal/locks.js b/lib/internal/locks.js index 054197bcaefcc6..05000e933f0b55 100644 --- a/lib/internal/locks.js +++ b/lib/internal/locks.js @@ -29,8 +29,13 @@ const { createEnumConverter, createDictionaryConverter, } = require('internal/webidl'); +const dc = require('diagnostics_channel'); const locks = internalBinding('locks'); +const lockRequestStartChannel = dc.channel('locks.request.start'); +const lockRequestGrantChannel = dc.channel('locks.request.grant'); +const lockRequestMissChannel = dc.channel('locks.request.miss'); +const lockRequestEndChannel = dc.channel('locks.request.end'); const kName = Symbol('kName'); const kMode = Symbol('kMode'); @@ -113,6 +118,30 @@ function convertLockError(error) { return error; } +function publishLockRequestStart(name, mode) { + if (lockRequestStartChannel.hasSubscribers) { + lockRequestStartChannel.publish({ name, mode }); + } +} + +function publishLockRequestGrant(name, mode) { + if (lockRequestGrantChannel.hasSubscribers) { + lockRequestGrantChannel.publish({ name, mode }); + } +} + +function publishLockRequestMiss(name, mode, ifAvailable) { + if (ifAvailable && lockRequestMissChannel.hasSubscribers) { + lockRequestMissChannel.publish({ name, mode }); + } +} + +function publishLockRequestEnd(name, mode, ifAvailable, steal, error) { + if (lockRequestEndChannel.hasSubscribers) { + lockRequestEndChannel.publish({ name, mode, ifAvailable, steal, error }); + } +} + // https://w3c.github.io/web-locks/#api-lock-manager class LockManager { constructor(symbol = undefined) { @@ -192,6 +221,7 @@ class LockManager { } const clientId = `node-${process.pid}-${threadId}`; + publishLockRequestStart(name, mode); // Handle requests with AbortSignal if (signal) { @@ -212,6 +242,8 @@ class LockManager { return undefined; } lockGranted = true; + publishLockRequestGrant(name, mode); + return callback(createLock(lock)); }); }; @@ -228,27 +260,49 @@ class LockManager { // When released promise settles, clean up listener and resolve main promise SafePromisePrototypeFinally( - PromisePrototypeThen(released, resolve, (error) => reject(convertLockError(error))), + PromisePrototypeThen( + released, + (result) => { + publishLockRequestEnd(name, mode, ifAvailable, steal, undefined); + resolve(result); + }, + (error) => { + const convertedError = convertLockError(error); + publishLockRequestEnd(name, mode, ifAvailable, steal, convertedError); + reject(convertedError); + }, + ), () => signal.removeEventListener('abort', abortListener), ); } catch (error) { signal.removeEventListener('abort', abortListener); - reject(convertLockError(error)); + const convertedError = convertLockError(error); + publishLockRequestEnd(name, mode, ifAvailable, steal, convertedError); + reject(convertedError); } }); } // When ifAvailable: true and lock is not available, C++ passes null to indicate no lock granted const wrapCallback = (internalLock) => { + if (internalLock === null) { + publishLockRequestMiss(name, mode, ifAvailable); + } else { + publishLockRequestGrant(name, mode); + } const lock = createLock(internalLock); return callback(lock); }; // Standard request without signal try { - return await locks.request(name, clientId, mode, steal, ifAvailable, wrapCallback); + const result = await locks.request(name, clientId, mode, steal, ifAvailable, wrapCallback); + publishLockRequestEnd(name, mode, ifAvailable, steal, undefined); + + return result; } catch (error) { const convertedError = convertLockError(error); + publishLockRequestEnd(name, mode, ifAvailable, steal, convertedError); throw convertedError; } } diff --git a/test/parallel/test-diagnostics-channel-web-locks.js b/test/parallel/test-diagnostics-channel-web-locks.js new file mode 100644 index 00000000000000..dec0daef9868a0 --- /dev/null +++ b/test/parallel/test-diagnostics-channel-web-locks.js @@ -0,0 +1,167 @@ +'use strict'; + +const common = require('../common'); +const { describe, it } = require('node:test'); +const assert = require('node:assert'); +const dc = require('node:diagnostics_channel'); + +function subscribe({ start, grant, miss, end }) { + if (start) dc.subscribe('locks.request.start', start); + if (grant) dc.subscribe('locks.request.grant', grant); + if (miss) dc.subscribe('locks.request.miss', miss); + if (end) dc.subscribe('locks.request.end', end); + + return () => { + if (start) dc.unsubscribe('locks.request.start', start); + if (grant) dc.unsubscribe('locks.request.grant', grant); + if (miss) dc.unsubscribe('locks.request.miss', miss); + if (end) dc.unsubscribe('locks.request.end', end); + }; +} + +describe('Web Locks diagnostics channel', () => { + it('emits start, grant, and end on success', async () => { + let startEvent; + const unsubscribe = subscribe({ + start: common.mustCall((e) => startEvent = e), + grant: common.mustCall(), + miss: common.mustNotCall(), + end: common.mustCall(), + }); + + try { + const result = await navigator.locks.request('normal-lock', async () => 'done'); + assert.strictEqual(result, 'done'); + assert.strictEqual(startEvent.name, 'normal-lock'); + assert.strictEqual(startEvent.mode, 'exclusive'); + } finally { + unsubscribe(); + } + }); + + it('emits start, miss, and end when lock is unavailable', async () => { + await navigator.locks.request('ifavailable-true-lock', common.mustCall(async () => { + let startEvent; + const unsubscribe = subscribe({ + start: common.mustCall((e) => startEvent = e), + grant: common.mustNotCall(), + miss: common.mustCall(), + end: common.mustCall(), + }); + + try { + const result = await navigator.locks.request( + 'ifavailable-true-lock', + { ifAvailable: true }, + (lock) => lock, + ); + + assert.strictEqual(result, null); + assert.strictEqual(startEvent.name, 'ifavailable-true-lock'); + assert.strictEqual(startEvent.mode, 'exclusive'); + } finally { + unsubscribe(); + } + })); + }); + + it('queued lock request emits start, grant, and end without miss', async () => { + // Outer fires first, inner is queued — so events arrive in insertion order + let outerStartEvent, innerStartEvent; + const unsubscribe = subscribe({ + start: common.mustCall((e) => (outerStartEvent ? innerStartEvent = e : outerStartEvent = e), 2), + grant: common.mustCall(2), + miss: common.mustNotCall(), + end: common.mustCall(2), + }); + + try { + let innerDone; + + const outerResult = await navigator.locks.request('ifavailable-false-lock', common.mustCall(async () => { + innerDone = navigator.locks.request( + 'ifavailable-false-lock', + { ifAvailable: false }, + common.mustCall(async (lock) => { + assert.ok(lock); + return 'inner-done'; + }), + ); + await new Promise((resolve) => setTimeout(resolve, 20)); + return 'outer-done'; + })); + + assert.strictEqual(outerResult, 'outer-done'); + assert.strictEqual(await innerDone, 'inner-done'); + + assert.strictEqual(outerStartEvent.name, 'ifavailable-false-lock'); + assert.strictEqual(outerStartEvent.mode, 'exclusive'); + assert.strictEqual(innerStartEvent.name, 'ifavailable-false-lock'); + assert.strictEqual(innerStartEvent.mode, 'exclusive'); + } finally { + unsubscribe(); + } + }); + + it('reports callback error in end event', async () => { + const expectedError = new Error('Callback error'); + let endEvent; + const unsubscribe = subscribe({ + start: common.mustCall(), + grant: common.mustCall(), + miss: common.mustNotCall(), + end: common.mustCall((e) => endEvent = e), + }); + + try { + await assert.rejects( + navigator.locks.request('error-lock', async () => { throw expectedError; }), + (error) => error === expectedError, + ); + + assert.strictEqual(endEvent.name, 'error-lock'); + assert.strictEqual(endEvent.mode, 'exclusive'); + assert.strictEqual(endEvent.error, expectedError); + } finally { + unsubscribe(); + } + }); + + it('stolen lock ends original request with AbortError', async () => { + let stolenEndEvent, stealerEndEvent; + const unsubscribe = subscribe({ + start: common.mustCall(2), + grant: common.mustCall(2), + miss: common.mustNotCall(), + end: common.mustCall((e) => (e.steal ? stealerEndEvent = e : stolenEndEvent = e), 2), + }); + + try { + let resolveGranted; + const granted = new Promise((r) => { resolveGranted = r; }); + + const originalRejected = assert.rejects( + navigator.locks.request('steal-lock', async () => { + resolveGranted(); + await new Promise((r) => setTimeout(r, 200)); + }), + { name: 'AbortError' }, + ); + + await granted; + await navigator.locks.request('steal-lock', { steal: true }, async () => {}); + await originalRejected; + + assert.strictEqual(stolenEndEvent.name, 'steal-lock'); + assert.strictEqual(stolenEndEvent.mode, 'exclusive'); + assert.strictEqual(stolenEndEvent.steal, false); + assert.strictEqual(stealerEndEvent.name, 'steal-lock'); + assert.strictEqual(stealerEndEvent.mode, 'exclusive'); + assert.strictEqual(stealerEndEvent.steal, true); + assert.strictEqual(stolenEndEvent.error.name, 'AbortError'); + assert.strictEqual(stealerEndEvent.error, undefined); + } finally { + unsubscribe(); + } + }); +}); From d3fd4a978b0a645d57f61b7e2b3a36e4c119276b Mon Sep 17 00:00:00 2001 From: Ilyas Shabi Date: Sun, 15 Mar 2026 15:08:02 +0100 Subject: [PATCH 024/106] worker: heap profile optimizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/62201 Reviewed-By: Anna Henningsen Reviewed-By: Yagiz Nizipli Reviewed-By: Colin Ihrig Reviewed-By: Juan José Arboleda Reviewed-By: theanarkh Reviewed-By: Gürgün Dayıoğlu --- src/node_worker.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node_worker.cc b/src/node_worker.cc index dccba51d507ed0..d2dd7a9e0e9e4f 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -1121,7 +1121,8 @@ static bool serializeProfile(Isolate* isolate, std::ostringstream& out_stream) { if (!profile) { return false; } - JSONWriter writer(out_stream, false); + profiler->StopSamplingHeapProfiler(); + JSONWriter writer(out_stream, true); writer.json_start(); writer.json_arraystart("samples"); @@ -1139,7 +1140,6 @@ static bool serializeProfile(Isolate* isolate, std::ostringstream& out_stream) { writer.json_objectend(); writer.json_end(); - profiler->StopSamplingHeapProfiler(); return true; } From 67c69750f43e8c4b7c5af756f6f98bcc6af16da8 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 15 Mar 2026 19:23:34 +0100 Subject: [PATCH 025/106] tools: validate all commits that are pushed to `main` PR-URL: https://github.com/nodejs/node/pull/62246 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Luigi Pinca Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Colin Ihrig --- .github/workflows/notify-on-push.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/notify-on-push.yml b/.github/workflows/notify-on-push.yml index 9b704b788261ba..605a896541f2f3 100644 --- a/.github/workflows/notify-on-push.yml +++ b/.github/workflows/notify-on-push.yml @@ -30,20 +30,16 @@ jobs: validateCommitMessage: name: Notify on Push on `main` with invalid message - if: github.repository == 'nodejs/node' # cannot use ubuntu-slim here because rtCamp/action-slack-notify is dockerized runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: Check commit message + - name: Validate commits + run: echo "$COMMITS" | npx -q core-validate-commit - id: commit-check - run: npx -q core-validate-commit "$COMMIT" env: - COMMIT: ${{ github.event.after }} + COMMITS: ${{ toJSON(github.event.commits) }} - name: Slack Notification - if: ${{ failure() && steps.commit-check.conclusion == 'failure' }} + if: ${{ failure() && steps.commit-check.conclusion == 'failure' && github.repository == 'nodejs/node' }} uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # 2.3.3 env: SLACK_COLOR: '#DE512A' From 531c64d04e2e27aa3ea743cbef32c79b5d9ec010 Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Sun, 15 Mar 2026 19:59:11 -0400 Subject: [PATCH 026/106] url: enable simdutf for ada MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/61477 Reviewed-By: Daniel Lemire Reviewed-By: Rafael Gonzaga Reviewed-By: Gürgün Dayıoğlu Reviewed-By: Robert Nagy --- deps/ada/ada.gyp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/deps/ada/ada.gyp b/deps/ada/ada.gyp index 4c8910dcb5c915..30054e63e567fd 100644 --- a/deps/ada/ada.gyp +++ b/deps/ada/ada.gyp @@ -6,10 +6,19 @@ { 'target_name': 'ada', 'type': 'static_library', - 'include_dirs': ['.'], + 'include_dirs': [ + '.', + '<(DEPTH)/deps/v8/third_party/simdutf', + ], 'direct_dependent_settings': { 'include_dirs': ['.'], }, + 'defines': [ + 'ADA_USE_SIMDUTF=1', + ], + 'dependencies': [ + '../../tools/v8_gypfiles/v8.gyp:simdutf', + ], 'sources': [ '<@(ada_sources)' ] }, ] From f976c9214daa80f02656498dae66f7b772114cc3 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Mon, 16 Mar 2026 11:35:48 +0100 Subject: [PATCH 027/106] doc: clarify that any truthy value of `shell` is part of DEP0190 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/62249 Reviewed-By: René Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- doc/api/deprecations.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 1e98f24d478644..d9621d10191563 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4164,7 +4164,7 @@ Type: Documentation-only `process.features.tls_alpn`, `process.features.tls_ocsp`, and `process.features.tls_sni` are deprecated, as their values are guaranteed to be identical to that of `process.features.tls`. -### DEP0190: Passing `args` to `node:child_process` `execFile`/`spawn` with `shell` option `true` +### DEP0190: Passing `args` to `node:child_process` `execFile`/`spawn` with `shell` option -#### `cShakeParams.customization` +#### `cShakeParams.name` -* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined} +* Type: {string} Must be `'cSHAKE128'`[^modern-algos] or `'cSHAKE256'`[^modern-algos] -The `customization` member represents the customization string. -The Node.js Web Crypto API implementation only supports zero-length customization -which is equivalent to not providing customization at all. +#### `cShakeParams.outputLength` + + + +* Type: {number} represents the requested output length in bits. #### `cShakeParams.functionName` @@ -1896,21 +1904,17 @@ functions based on cSHAKE. The Node.js Web Crypto API implementation only supports zero-length functionName which is equivalent to not providing functionName at all. -#### `cShakeParams.length` +#### `cShakeParams.customization` -* Type: {number} represents the requested output length in bits. - -#### `cShakeParams.name` - - +* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined} -* Type: {string} Must be `'cSHAKE128'`[^modern-algos] or `'cSHAKE256'`[^modern-algos] +The `customization` member represents the customization string. +The Node.js Web Crypto API implementation only supports zero-length customization +which is equivalent to not providing customization at all. ### Class: `EcdhKeyDeriveParams` @@ -2387,6 +2391,10 @@ added: v24.8.0 #### `kmacParams.algorithm` @@ -2397,25 +2405,25 @@ added: v24.8.0 * Type: {string} Must be `'KMAC128'` or `'KMAC256'`. -#### `kmacParams.customization` +#### `kmacParams.outputLength` -* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined} +* Type: {number} -The `customization` member represents the optional customization string. +The length of the output in bytes. This must be a positive integer. -#### `kmacParams.length` +#### `kmacParams.customization` -* Type: {number} +* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined} -The length of the output in bytes. This must be a positive integer. +The `customization` member represents the optional customization string. ### Class: `Pbkdf2Params` diff --git a/lib/internal/crypto/hash.js b/lib/internal/crypto/hash.js index 3f34468e55e99f..e549c72fccc4bc 100644 --- a/lib/internal/crypto/hash.js +++ b/lib/internal/crypto/hash.js @@ -223,7 +223,7 @@ async function asyncDigest(algorithm, data) { kCryptoJobAsync, normalizeHashName(algorithm.name), data, - algorithm.length)); + algorithm.outputLength)); } throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError'); diff --git a/lib/internal/crypto/mac.js b/lib/internal/crypto/mac.js index a31c3ddb0d9484..1ad4e27c6a8d39 100644 --- a/lib/internal/crypto/mac.js +++ b/lib/internal/crypto/mac.js @@ -234,7 +234,7 @@ function kmacSignVerify(key, data, algorithm, signature) { key[kKeyObject][kHandle], algorithm.name, algorithm.customization, - algorithm.length / 8, + algorithm.outputLength / 8, data, signature)); } diff --git a/lib/internal/crypto/webidl.js b/lib/internal/crypto/webidl.js index 4162d84d426f53..2b8ac167bc3627 100644 --- a/lib/internal/crypto/webidl.js +++ b/lib/internal/crypto/webidl.js @@ -591,14 +591,14 @@ converters.CShakeParams = createDictionaryConverter( 'CShakeParams', [ ...new SafeArrayIterator(dictAlgorithm), { - key: 'length', + key: 'outputLength', converter: (V, opts) => converters['unsigned long'](V, { ...opts, enforceRange: true }), validator: (V, opts) => { // The Web Crypto spec allows for SHAKE output length that are not multiples of // 8. We don't. if (V % 8) - throw lazyDOMException('Unsupported CShakeParams length', 'NotSupportedError'); + throw lazyDOMException('Unsupported CShakeParams outputLength', 'NotSupportedError'); }, required: true, }, @@ -881,13 +881,13 @@ converters.KmacParams = createDictionaryConverter( 'KmacParams', [ ...new SafeArrayIterator(dictAlgorithm), { - key: 'length', + key: 'outputLength', converter: (V, opts) => converters['unsigned long'](V, { ...opts, enforceRange: true }), validator: (V, opts) => { // The Web Crypto spec allows for KMAC output length that are not multiples of 8. We don't. if (V % 8) - throw lazyDOMException('Unsupported KmacParams length', 'NotSupportedError'); + throw lazyDOMException('Unsupported KmacParams outputLength', 'NotSupportedError'); }, required: true, }, diff --git a/test/fixtures/crypto/kmac.js b/test/fixtures/crypto/kmac.js index 86dec424bad9b1..cc1870af2bb04f 100644 --- a/test/fixtures/crypto/kmac.js +++ b/test/fixtures/crypto/kmac.js @@ -13,7 +13,7 @@ module.exports = function() { ]), data: Buffer.from([0x00, 0x01, 0x02, 0x03]), customization: undefined, - length: 256, + outputLength: 256, expected: Buffer.from([ 0xe5, 0x78, 0x0b, 0x0d, 0x3e, 0xa6, 0xf7, 0xd3, 0xa4, 0x29, 0xc5, 0x70, 0x6a, 0xa4, 0x3a, 0x00, 0xfa, 0xdb, 0xd7, 0xd4, 0x96, 0x28, 0x83, 0x9e, @@ -30,7 +30,7 @@ module.exports = function() { ]), data: Buffer.from([0x00, 0x01, 0x02, 0x03]), customization: Buffer.from('My Tagged Application'), - length: 256, + outputLength: 256, expected: Buffer.from([ 0x3b, 0x1f, 0xba, 0x96, 0x3c, 0xd8, 0xb0, 0xb5, 0x9e, 0x8c, 0x1a, 0x6d, 0x71, 0x88, 0x8b, 0x71, 0x43, 0x65, 0x1a, 0xf8, 0xba, 0x0a, 0x70, 0x70, @@ -47,7 +47,7 @@ module.exports = function() { ]), data: Buffer.from(Array.from({ length: 200 }, (_, i) => i)), // 0x00-0xC7 customization: Buffer.from('My Tagged Application'), - length: 256, + outputLength: 256, expected: Buffer.from([ 0x1f, 0x5b, 0x4e, 0x6c, 0xca, 0x02, 0x20, 0x9e, 0x0d, 0xcb, 0x5c, 0xa6, 0x35, 0xb8, 0x9a, 0x15, 0xe2, 0x71, 0xec, 0xc7, 0x60, 0x07, 0x1d, 0xfd, @@ -64,7 +64,7 @@ module.exports = function() { ]), data: Buffer.from([0x00, 0x01, 0x02, 0x03]), customization: Buffer.from('My Tagged Application'), - length: 512, + outputLength: 512, expected: Buffer.from([ 0x20, 0xc5, 0x70, 0xc3, 0x13, 0x46, 0xf7, 0x03, 0xc9, 0xac, 0x36, 0xc6, 0x1c, 0x03, 0xcb, 0x64, 0xc3, 0x97, 0x0d, 0x0c, 0xfc, 0x78, 0x7e, 0x9b, @@ -84,7 +84,7 @@ module.exports = function() { ]), data: Buffer.from(Array.from({ length: 200 }, (_, i) => i)), // 0x00-0xC7 customization: undefined, - length: 512, + outputLength: 512, expected: Buffer.from([ 0x75, 0x35, 0x8c, 0xf3, 0x9e, 0x41, 0x49, 0x4e, 0x94, 0x97, 0x07, 0x92, 0x7c, 0xee, 0x0a, 0xf2, 0x0a, 0x3f, 0xf5, 0x53, 0x90, 0x4c, 0x86, 0xb0, @@ -104,7 +104,7 @@ module.exports = function() { ]), data: Buffer.from(Array.from({ length: 200 }, (_, i) => i)), // 0x00-0xC7 customization: Buffer.from('My Tagged Application'), - length: 512, + outputLength: 512, expected: Buffer.from([ 0xb5, 0x86, 0x18, 0xf7, 0x1f, 0x92, 0xe1, 0xd5, 0x6c, 0x1b, 0x8c, 0x55, 0xdd, 0xd7, 0xcd, 0x18, 0x8b, 0x97, 0xb4, 0xca, 0x4d, 0x99, 0x83, 0x1e, diff --git a/test/fixtures/webcrypto/supports-modern-algorithms.mjs b/test/fixtures/webcrypto/supports-modern-algorithms.mjs index 76d5e805cbc0e7..eafb95c559a0f7 100644 --- a/test/fixtures/webcrypto/supports-modern-algorithms.mjs +++ b/test/fixtures/webcrypto/supports-modern-algorithms.mjs @@ -17,17 +17,17 @@ const X25519 = await subtle.generateKey('X25519', false, ['deriveBits', 'deriveK export const vectors = { 'digest': [ [false, 'cSHAKE128'], - [shake128, { name: 'cSHAKE128', length: 128 }], - [shake128, { name: 'cSHAKE128', length: 128, functionName: Buffer.alloc(0), customization: Buffer.alloc(0) }], - [false, { name: 'cSHAKE128', length: 128, functionName: Buffer.alloc(1) }], - [false, { name: 'cSHAKE128', length: 128, customization: Buffer.alloc(1) }], - [false, { name: 'cSHAKE128', length: 127 }], + [shake128, { name: 'cSHAKE128', outputLength: 128 }], + [shake128, { name: 'cSHAKE128', outputLength: 128, functionName: Buffer.alloc(0), customization: Buffer.alloc(0) }], + [false, { name: 'cSHAKE128', outputLength: 128, functionName: Buffer.alloc(1) }], + [false, { name: 'cSHAKE128', outputLength: 128, customization: Buffer.alloc(1) }], + [false, { name: 'cSHAKE128', outputLength: 127 }], [false, 'cSHAKE256'], - [shake256, { name: 'cSHAKE256', length: 256 }], - [shake256, { name: 'cSHAKE256', length: 256, functionName: Buffer.alloc(0), customization: Buffer.alloc(0) }], - [false, { name: 'cSHAKE256', length: 256, functionName: Buffer.alloc(1) }], - [false, { name: 'cSHAKE256', length: 256, customization: Buffer.alloc(1) }], - [false, { name: 'cSHAKE256', length: 255 }], + [shake256, { name: 'cSHAKE256', outputLength: 256 }], + [shake256, { name: 'cSHAKE256', outputLength: 256, functionName: Buffer.alloc(0), customization: Buffer.alloc(0) }], + [false, { name: 'cSHAKE256', outputLength: 256, functionName: Buffer.alloc(1) }], + [false, { name: 'cSHAKE256', outputLength: 256, customization: Buffer.alloc(1) }], + [false, { name: 'cSHAKE256', outputLength: 255 }], ], 'sign': [ [pqc, 'ML-DSA-44'], @@ -44,8 +44,8 @@ export const vectors = { [false, 'Argon2id'], [false, 'KMAC128'], [false, 'KMAC256'], - [kmac, { name: 'KMAC128', length: 256 }], - [kmac, { name: 'KMAC256', length: 256 }], + [kmac, { name: 'KMAC128', outputLength: 256 }], + [kmac, { name: 'KMAC256', outputLength: 256 }], ], 'generateKey': [ [pqc, 'ML-DSA-44'], diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 89f0cefdb6363e..cba3d03b9038fd 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -34,7 +34,7 @@ Last update: - wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi - wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi - web-locks: https://github.com/web-platform-tests/wpt/tree/10a122a6bc/web-locks -- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/6a1c545d77/WebCryptoAPI +- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/0acea989ac/WebCryptoAPI - webidl: https://github.com/web-platform-tests/wpt/tree/63ca529a02/webidl - webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/2f96fa1996/webidl/ecmascript-binding/es-exceptions - webmessaging/broadcastchannel: https://github.com/web-platform-tests/wpt/tree/6495c91853/webmessaging/broadcastchannel diff --git a/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js b/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js index d0c23c09ada4a9..8be50b56097e89 100644 --- a/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js +++ b/test/fixtures/wpt/WebCryptoAPI/digest/cshake.tentative.https.any.js @@ -162,7 +162,7 @@ Object.keys(digestedData).forEach(function (alg) { Object.keys(sourceData).forEach(function (size) { promise_test(function (test) { return crypto.subtle - .digest({ name: alg, length: length }, sourceData[size]) + .digest({ name: alg, outputLength: length }, sourceData[size]) .then(function (result) { assert_true( equalBuffers(result, digestedData[alg][length][size]), @@ -183,7 +183,7 @@ Object.keys(digestedData).forEach(function (alg) { buffer[0] = sourceData[size][0]; return alg; }, - length + outputLength: length }, buffer) .then(function (result) { assert_true( @@ -196,7 +196,7 @@ Object.keys(digestedData).forEach(function (alg) { promise_test(function (test) { var buffer = new Uint8Array(sourceData[size]); var promise = crypto.subtle - .digest({ name: alg, length: length }, buffer) + .digest({ name: alg, outputLength: length }, buffer) .then(function (result) { assert_true( equalBuffers(result, digestedData[alg][length][size]), @@ -217,7 +217,7 @@ Object.keys(digestedData).forEach(function (alg) { buffer.buffer.transfer(); return alg; }, - length + outputLength: length }, buffer) .then(function (result) { assert_true( @@ -230,7 +230,7 @@ Object.keys(digestedData).forEach(function (alg) { promise_test(function (test) { var buffer = new Uint8Array(sourceData[size]); var promise = crypto.subtle - .digest({ name: alg, length: length }, buffer) + .digest({ name: alg, outputLength: length }, buffer) .then(function (result) { assert_true( equalBuffers(result, digestedData[alg][length][size]), diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js index f3cc9b4cd1dbfd..b966c12b4ed07c 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac.js @@ -15,7 +15,7 @@ function run_test() { var promise = importVectorKeys(vector, ["verify", "sign"]) .then(function(vector) { promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -48,7 +48,7 @@ function run_test() { var signature = copyBuffer(vector.signature); signature[0] = 255 - signature[0]; var algorithmParams = { - length: vector.length, + outputLength: vector.outputLength, get name() { signature[0] = vector.signature[0]; return vector.algorithm; @@ -81,7 +81,7 @@ function run_test() { .then(function(vector) { promise_test(function(test) { var signature = copyBuffer(vector.signature); - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -115,7 +115,7 @@ function run_test() { signature.buffer.transfer(); return vector.algorithm; }, - length: vector.length + outputLength: vector.outputLength }; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; @@ -144,7 +144,7 @@ function run_test() { .then(function(vector) { promise_test(function(test) { var signature = copyBuffer(vector.signature); - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -175,7 +175,7 @@ function run_test() { var plaintext = copyBuffer(vector.plaintext); plaintext[0] = 255 - plaintext[0]; var algorithmParams = { - length: vector.length, + outputLength: vector.outputLength, get name() { plaintext[0] = vector.plaintext[0]; return vector.algorithm; @@ -208,7 +208,7 @@ function run_test() { .then(function(vector) { promise_test(function(test) { var plaintext = copyBuffer(vector.plaintext); - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -242,7 +242,7 @@ function run_test() { plaintext.buffer.transfer(); return vector.algorithm; }, - length: vector.length + outputLength: vector.outputLength }; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; @@ -271,7 +271,7 @@ function run_test() { .then(function(vector) { promise_test(function(test) { var plaintext = copyBuffer(vector.plaintext); - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -301,7 +301,7 @@ function run_test() { var promise = importVectorKeys(vector, ["sign"]) .then(function(vector) { promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -326,7 +326,7 @@ function run_test() { var promise = importVectorKeys(vector, ["verify", "sign"]) .then(function(vectors) { promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -363,7 +363,7 @@ function run_test() { return importVectorKeys(vector, ["verify", "sign"]) .then(function(vectors) { promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -401,7 +401,7 @@ function run_test() { return importVectorKeys(vector, ["verify", "sign"]) .then(function(vector) { promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -438,7 +438,7 @@ function run_test() { var plaintext = copyBuffer(vector.plaintext); plaintext[0] = 255 - plaintext[0]; promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -470,7 +470,7 @@ function run_test() { var signature = copyBuffer(vector.signature); signature[0] = 255 - signature[0]; promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -501,7 +501,7 @@ function run_test() { .then(function(vector) { var signature = vector.signature.slice(1); // Drop first byte promise_test(function(test) { - var algorithmParams = {name: vector.algorithm, length: vector.length}; + var algorithmParams = {name: vector.algorithm, outputLength: vector.outputLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } @@ -531,8 +531,8 @@ function run_test() { var promise = importVectorKeys(vector, ["verify", "sign"]) .then(function(vector) { promise_test(function(test) { - var differentLength = vector.length === 256 ? 512 : 256; - var algorithmParams = {name: vector.algorithm, length: differentLength}; + var differentLength = vector.outputLength === 256 ? 512 : 256; + var algorithmParams = {name: vector.algorithm, outputLength: differentLength}; if (vector.customization !== undefined) { algorithmParams.customization = vector.customization; } diff --git a/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac_vectors.js b/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac_vectors.js index 39d0efe71ba3e2..6b35cab168c9c6 100644 --- a/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac_vectors.js +++ b/test/fixtures/wpt/WebCryptoAPI/sign_verify/kmac_vectors.js @@ -6,7 +6,7 @@ function getTestVectors() { // Sample #1 - KMAC128, no customization name: "KMAC128 with no customization", algorithm: "KMAC128", - length: 256, + outputLength: 256, keyBuffer: new Uint8Array([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, @@ -25,7 +25,7 @@ function getTestVectors() { // Sample #2 - KMAC128, with customization name: "KMAC128 with customization", algorithm: "KMAC128", - length: 256, + outputLength: 256, keyBuffer: new Uint8Array([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, @@ -47,7 +47,7 @@ function getTestVectors() { // Sample #3 - KMAC128, large data, with customization name: "KMAC128 with large data and customization", algorithm: "KMAC128", - length: 256, + outputLength: 256, keyBuffer: new Uint8Array([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, @@ -69,7 +69,7 @@ function getTestVectors() { // Sample #4 - KMAC256, with customization, 512-bit output name: "KMAC256 with customization and 512-bit output", algorithm: "KMAC256", - length: 512, + outputLength: 512, keyBuffer: new Uint8Array([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, @@ -94,7 +94,7 @@ function getTestVectors() { // Sample #5 - KMAC256, large data, no customization, 512-bit output name: "KMAC256 with large data and no customization", algorithm: "KMAC256", - length: 512, + outputLength: 512, keyBuffer: new Uint8Array([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, @@ -116,7 +116,7 @@ function getTestVectors() { // Sample #6 - KMAC256, large data, with customization, 512-bit output name: "KMAC256 with large data and customization", algorithm: "KMAC256", - length: 512, + outputLength: 512, keyBuffer: new Uint8Array([ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index ba7488a89a20b9..02c16cd1074435 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -96,7 +96,7 @@ "path": "web-locks" }, "WebCryptoAPI": { - "commit": "6a1c545d778f115c84a1c27c25484afd442b89d8", + "commit": "0acea989ac21842d6545d16594f1a05491c6076e", "path": "WebCryptoAPI" }, "webidl": { diff --git a/test/parallel/test-webcrypto-digest.js b/test/parallel/test-webcrypto-digest.js index 4d22006937f8cb..4a28d88dcd72c3 100644 --- a/test/parallel/test-webcrypto-digest.js +++ b/test/parallel/test-webcrypto-digest.js @@ -19,8 +19,8 @@ const kTests = [ if (!process.features.openssl_is_boringssl) { kTests.push( - [{ name: 'cSHAKE128', length: 256 }, ['shake128', { outputLength: 256 >> 3 }], 256], - [{ name: 'cSHAKE256', length: 512 }, ['shake256', { outputLength: 512 >> 3 }], 512], + [{ name: 'cSHAKE128', outputLength: 256 }, ['shake128', { outputLength: 256 >> 3 }], 256], + [{ name: 'cSHAKE256', outputLength: 512 }, ['shake256', { outputLength: 512 >> 3 }], 512], ['SHA3-256', ['sha3-256'], 256], ['SHA3-384', ['sha3-384'], 384], ['SHA3-512', ['sha3-512'], 512], @@ -223,10 +223,10 @@ async function testDigest(size, alg) { function applyXOF(name) { if (name.match(/cshake128/i)) { - return { name, length: 256 }; + return { name, outputLength: 256 }; } if (name.match(/cshake256/i)) { - return { name, length: 512 }; + return { name, outputLength: 512 }; } return name; @@ -259,13 +259,13 @@ function applyXOF(name) { if (getHashes().includes('shake128')) { (async () => { assert.deepStrictEqual( - new Uint8Array(await subtle.digest({ name: 'cSHAKE128', length: 0 }, Buffer.alloc(1))), + new Uint8Array(await subtle.digest({ name: 'cSHAKE128', outputLength: 0 }, Buffer.alloc(1))), new Uint8Array(0), ); - await assert.rejects(subtle.digest({ name: 'cSHAKE128', length: 7 }, Buffer.alloc(1)), { + await assert.rejects(subtle.digest({ name: 'cSHAKE128', outputLength: 7 }, Buffer.alloc(1)), { name: 'NotSupportedError', - message: 'Unsupported CShakeParams length', + message: 'Unsupported CShakeParams outputLength', }); })().then(common.mustCall()); } diff --git a/test/parallel/test-webcrypto-sign-verify-kmac.js b/test/parallel/test-webcrypto-sign-verify-kmac.js index c30196a94d9fb6..d41095e0893d97 100644 --- a/test/parallel/test-webcrypto-sign-verify-kmac.js +++ b/test/parallel/test-webcrypto-sign-verify-kmac.js @@ -19,7 +19,7 @@ async function testVerify({ algorithm, key, data, customization, - length, + outputLength, expected }) { const [ verifyKey, @@ -46,7 +46,7 @@ async function testVerify({ algorithm, const signParams = { name: algorithm, - length, + outputLength, customization, }; @@ -112,7 +112,7 @@ async function testVerify({ algorithm, { assert(!(await subtle.verify({ ...signParams, - length: length === 256 ? 512 : 256, + outputLength: outputLength === 256 ? 512 : 256, }, verifyKey, expected, data))); } } @@ -121,7 +121,7 @@ async function testSign({ algorithm, key, data, customization, - length, + outputLength, expected }) { const [ signKey, @@ -148,7 +148,7 @@ async function testSign({ algorithm, const signParams = { name: algorithm, - length, + outputLength, customization, }; diff --git a/test/parallel/test-webcrypto-sign-verify.js b/test/parallel/test-webcrypto-sign-verify.js index 8b034e005b29a4..26e66d9aa0fa8b 100644 --- a/test/parallel/test-webcrypto-sign-verify.js +++ b/test/parallel/test-webcrypto-sign-verify.js @@ -118,12 +118,12 @@ if (hasOpenSSL(3)) { const signature = await subtle.sign({ name, - length: 256, + outputLength: 256, }, key, ec.encode(data)); assert(await subtle.verify({ name, - length: 256, + outputLength: 256, }, key, signature, ec.encode(data))); } From 22fc8078e8eb32911332b27e467a0f355dd245a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 23:02:31 +0000 Subject: [PATCH 032/106] tools: bump flatted from 3.3.3 to 3.4.1 in /tools/eslint Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.3 to 3.4.1. - [Commits](https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.1) --- updated-dependencies: - dependency-name: flatted dependency-version: 3.4.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] PR-URL: https://github.com/nodejs/node/pull/62255 Reviewed-By: Antoine du Hamel Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- tools/eslint/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/eslint/package-lock.json b/tools/eslint/package-lock.json index b8a33ce4881db3..75862d33c7e79c 100644 --- a/tools/eslint/package-lock.json +++ b/tools/eslint/package-lock.json @@ -1257,9 +1257,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", "license": "ISC" }, "node_modules/format": { From 3bdc955b631e58432b4e911fce72807fc9e0aff4 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 16 Mar 2026 20:59:29 -0400 Subject: [PATCH 033/106] deps: update sqlite to 3.51.3 PR-URL: https://github.com/nodejs/node/pull/62256 Reviewed-By: Antoine du Hamel Reviewed-By: Colin Ihrig Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Luigi Pinca Reviewed-By: Chemi Atlow Reviewed-By: Edy Silva --- deps/sqlite/sqlite3.c | 8344 ++++++++++++++++---------------------- deps/sqlite/sqlite3.h | 253 +- deps/sqlite/sqlite3ext.h | 11 +- 3 files changed, 3489 insertions(+), 5119 deletions(-) diff --git a/deps/sqlite/sqlite3.c b/deps/sqlite/sqlite3.c index 76d2887bf034c6..851a2504cd0bde 100644 --- a/deps/sqlite/sqlite3.c +++ b/deps/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.52.0. By combining all the individual C code files into this +** version 3.51.3. 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 @@ -18,7 +18,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** 557aeb43869d3585137b17690cb3b64f7de6 with changes in files: +** 737ae4a34738ffa0c3ff7f9bb18df914dd1c with changes in files: ** ** */ @@ -467,12 +467,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.52.0" -#define SQLITE_VERSION_NUMBER 3052000 -#define SQLITE_SOURCE_ID "2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.52.0" -#define SQLITE_SCM_DATETIME "2026-03-06T16:01:44.367Z" +#define SQLITE_VERSION "3.51.3" +#define SQLITE_VERSION_NUMBER 3051003 +#define SQLITE_SOURCE_ID "2026-03-13 10:38:09 737ae4a34738ffa0c3ff7f9bb18df914dd1cad163f28fd6b6e114a344fe6d618" +#define SQLITE_SCM_BRANCH "branch-3.51" +#define SQLITE_SCM_TAGS "release version-3.51.3" +#define SQLITE_SCM_DATETIME "2026-03-13T10:38:09.694Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1811,7 +1811,7 @@ typedef const char *sqlite3_filename; ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** -** ^The xSetSystemCall(), xGetSystemCall(), and xNextSystemCall() interfaces +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided ** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can @@ -2888,15 +2888,12 @@ struct sqlite3_mem_methods { ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] **
SQLITE_DBCONFIG_STMT_SCANSTATUS
**
The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** [SQLITE_ENABLE_STMT_SCANSTATUS] builds. In this case, it sets or clears -** a flag that enables collection of run-time performance statistics -** used by [sqlite3_stmt_scanstatus_v2()] and the [nexec and ncycle] -** columns of the [bytecode virtual table]. -** For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is -** [sqlite3_prepare|prepared] and when it is [sqlite3_step|stepped]. -** The flag is set (collection of statistics is enabled) by default. -**

This option takes two arguments: an integer and a pointer to +** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears +** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() +** statistics. For statistics to be collected, the flag must be set on +** the database handle both when the SQL statement is prepared and when it +** is stepped. The flag is set (collection of statistics is enabled) +** by default.

This option takes two arguments: an integer and a pointer to ** an integer. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after @@ -2969,22 +2966,6 @@ struct sqlite3_mem_methods { ** comments are allowed in SQL text after processing the first argument. **

** -** [[SQLITE_DBCONFIG_FP_DIGITS]] -**
SQLITE_DBCONFIG_FP_DIGITS
-**
The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines -** the number of significant digits that SQLite will attempt to preserve when -** converting floating point numbers (IEEE 754 "doubles") into text. The -** default value 17, as of SQLite version 3.52.0. The value was 15 in all -** prior versions.

-** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is a small integer, between 3 and 23, or -** zero. The FP_DIGITS setting is changed to that small integer, or left -** altered if the first argument is zero or out of range. The second argument -** is a pointer to an integer. If the pointer is not NULL, then the value of -** the FP_DIGITS setting, after possibly being modified by the first -** arguments, is written into the integer to which the second argument points. -**

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

Arguments To SQLITE_DBCONFIG Options

@@ -3002,10 +2983,9 @@ struct sqlite3_mem_methods { ** the first argument. ** **

While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME], -** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options -** are different. See the documentation of those exceptional options for -** details. +** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] +** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the +** documentation of those exceptional options for details. */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ @@ -3030,8 +3010,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4513,7 +4492,6 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); **

  • sqlite3_errmsg() **
  • sqlite3_errmsg16() **
  • sqlite3_error_offset() -**
  • sqlite3_db_handle() ** ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -4560,7 +4538,7 @@ SQLITE_API const char *sqlite3_errstr(int); SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* -** CAPI3REF: Set Error Code And Message +** CAPI3REF: Set Error Codes And Message ** METHOD: sqlite3 ** ** Set the error code of the database handle passed as the first argument @@ -4679,10 +4657,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
    SQLITE_LIMIT_EXPR_DEPTH
    **
    The maximum depth of the parse tree on any expression.
    )^ ** -** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(
    SQLITE_LIMIT_PARSER_DEPTH
    -**
    The maximum depth of the LALR(1) parser stack used to analyze -** input SQL statements.
    )^ -** ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    **
    The maximum number of terms in a compound SELECT statement.
    )^ ** @@ -4727,7 +4701,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 -#define SQLITE_LIMIT_PARSER_DEPTH 12 /* ** CAPI3REF: Prepare Flags @@ -4772,29 +4745,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** fails, the sqlite3_prepare_v3() call returns the same error indications ** with or without this flag; it just omits the call to [sqlite3_log()] that ** logs the error. -** -** [[SQLITE_PREPARE_FROM_DDL]]
    SQLITE_PREPARE_FROM_DDL
    -**
    The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce -** security constraints that would otherwise only be enforced when parsing -** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag -** causes the SQL compiler to treat the SQL statement being prepared as if -** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and -** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called -** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only -** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice -** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that -** is derived from parts of the database schema. In particular, virtual -** table implementations that run SQL statements that are derived from -** arguments to their CREATE VIRTUAL TABLE statement should always use -** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to -** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks. ** */ #define SQLITE_PREPARE_PERSISTENT 0x01 #define SQLITE_PREPARE_NORMALIZE 0x02 #define SQLITE_PREPARE_NO_VTAB 0x04 #define SQLITE_PREPARE_DONT_LOG 0x10 -#define SQLITE_PREPARE_FROM_DDL 0x20 /* ** CAPI3REF: Compiling An SQL Statement @@ -4808,9 +4764,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** 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 -** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times -** needed for special purpose or to pass along security restrictions. +** [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 @@ -5215,8 +5170,8 @@ typedef struct sqlite3_context sqlite3_context; ** it should be a pointer to well-formed UTF16 text. ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then ** it should be a pointer to a well-formed unicode string that is -** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT, -** or UTF16 otherwise. +** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 +** otherwise. ** ** [[byte-order determination rules]] ^The byte-order of ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) @@ -5262,15 +5217,10 @@ typedef struct sqlite3_context sqlite3_context; ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** -** ^The sixth argument (the E argument) -** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of -** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE] to specify the encoding of the text in the -** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the -** string argument is both UTF-8 encoded and is zero-terminated. In other -** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at -** least N+1 bytes and that the Z[N] byte is zero. If -** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the +** ^The sixth argument to sqlite3_bind_text64() must be one of +** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] +** to specify the encoding of the text in the third parameter. If +** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior ** is undefined. @@ -6137,51 +6087,6 @@ SQLITE_API int sqlite3_create_window_function( ** ** These constants define integer codes that represent the various ** text encodings supported by SQLite. -** -**
    -** [[SQLITE_UTF8]]
    SQLITE_UTF8
    Text is encoding as UTF-8
    -** -** [[SQLITE_UTF16LE]]
    SQLITE_UTF16LE
    Text is encoding as UTF-16 -** with each code point being expressed "little endian" - the least significant -** byte first. This is the usual encoding, for example on Windows.
    -** -** [[SQLITE_UTF16BE]]
    SQLITE_UTF16BE
    Text is encoding as UTF-16 -** with each code point being expressed "big endian" - the most significant -** byte first. This encoding is less common, but is still sometimes seen, -** specially on older systems. -** -** [[SQLITE_UTF16]]
    SQLITE_UTF16
    Text is encoding as UTF-16 -** with each code point being expressed either little endian or as big -** endian, according to the native endianness of the host computer. -** -** [[SQLITE_ANY]]
    SQLITE_ANY
    This encoding value may only be used -** to declare the preferred text for [application-defined SQL functions] -** created using [sqlite3_create_function()] and similar. If the preferred -** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep -** parameter) is SQLITE_ANY, that indicates that the function does not have -** a preference regarding the text encoding of its parameters and can take -** any text encoding that the SQLite core find convenient to supply. This -** option is deprecated. Please do not use it in new applications. -** -** [[SQLITE_UTF16_ALIGNED]]
    SQLITE_UTF16_ALIGNED
    This encoding -** value may be used as the 3rd parameter (the eTextRep parameter) to -** [sqlite3_create_collation()] and similar. This encoding value means -** that the application-defined collating sequence created expects its -** input strings to be in UTF16 in native byte order, and that the start -** of the strings must be aligned to a 2-byte boundary. -** -** [[SQLITE_UTF8_ZT]]
    SQLITE_UTF8_ZT
    This option can only be -** used to specify the text encoding to strings input to [sqlite3_result_text64()] -** and [sqlite3_bind_text64()]. It means that the input string (call it "z") -** is UTF-8 encoded and that it is zero-terminated. If the length parameter -** (call it "n") is non-negative, this encoding option means that the caller -** guarantees that z array contains at least n+1 bytes and that the z[n] -** byte has a value of zero. -** This option gives the same output as SQLITE_UTF8, but can be more efficient -** by avoiding the need to make a copy of the input string, in some cases. -** However, if z is allocated to hold fewer than n+1 bytes or if the -** z[n] byte is not zero, undefined behavior may result. -**
    */ #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ @@ -6189,7 +6094,6 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ -#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */ /* ** CAPI3REF: Function Flags @@ -6695,14 +6599,10 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi ** ** There is no limit (other than available memory) on the number of different ** client data pointers (with different names) that can be attached to a -** single database connection. However, the current implementation stores -** the content on a linked list. Insert and retrieval performance will -** be proportional to the number of entries. The design use case, and -** the use case for which the implementation is optimized, is -** that an application will store only small number of client data names, -** typically just one or two. This interface is not intended to be a -** generalized key/value store for thousands or millions of keys. It -** will work for that, but performance might be disappointing. +** single database connection. However, the implementation is optimized +** for the case of having only one or two different client data names. +** Applications and wrapper libraries are discouraged from using more than +** one client data name each. ** ** There is no way to enumerate the client data pointers ** associated with a database connection. The N parameter can be thought @@ -6810,14 +6710,10 @@ typedef void (*sqlite3_destructor_type)(void*); ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an +** ^The sqlite3_result_text64() interface sets the return value of an ** application-defined function to be a text string in an encoding -** specified the E parameter, which must be one -** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that -** the result text is both UTF-8 and zero-terminated. In other words, -** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that -** the Z[N] is zero. +** specified by the fifth (and last) parameter, which must be one +** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces @@ -6904,7 +6800,7 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int); SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); SQLITE_API void sqlite3_result_null(sqlite3_context*); SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n, +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); @@ -7843,7 +7739,7 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The sqlite3_load_extension() interface attempts to load an ** [SQLite extension] library contained in the file zFile. If ** the file cannot be loaded directly, attempts are made to load -** with various operating-system specific filename extensions added. +** with various operating-system specific extensions added. ** So for example, if "samplelib" cannot be loaded, then names like ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might ** be tried also. @@ -7851,10 +7747,10 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The entry point is zProc. ** ^(zProc may be 0, in which case SQLite will try to come up with an ** entry point name on its own. It first tries "sqlite3_extension_init". -** If that does not work, it tries names of the form "sqlite3_X_init" -** where X consists of the lower-case equivalent of all ASCII alphabetic -** characters or all ASCII alphanumeric characters in the filename from -** the last "/" to the first following "." and omitting any initial "lib".)^ +** If that does not work, it constructs a name "sqlite3_X_init" where +** X consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the @@ -9147,22 +9043,17 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ** pass the returned value to [sqlite3_free()] to avoid a memory leak. ** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ** string in [sqlite3_str] object X is zero bytes long. -** -** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object -** X and the string content it contains. Calling sqlite3_str_free(X) is -** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)). */ SQLITE_API char *sqlite3_str_finish(sqlite3_str*); -SQLITE_API void sqlite3_str_free(sqlite3_str*); /* ** CAPI3REF: Add Content To A Dynamic String ** METHOD: sqlite3_str ** -** These interfaces add or remove content to an sqlite3_str object -** previously obtained from [sqlite3_str_new()]. +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. ** ** ^The [sqlite3_str_appendf(X,F,...)] and ** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] @@ -9185,10 +9076,6 @@ SQLITE_API void sqlite3_str_free(sqlite3_str*); ** ^The [sqlite3_str_reset(X)] method resets the string under construction ** inside [sqlite3_str] object X back to zero bytes in length. ** -** ^The [sqlite3_str_truncate(X,N)] method changes the length of the string -** under construction to be N bytes are less. This routine is a no-op if -** N is negative or if the string is already N bytes or smaller in size. -** ** These methods do not return a result code. ^If an error occurs, that fact ** is recorded in the [sqlite3_str] object and can be recovered by a ** subsequent call to [sqlite3_str_errcode(X)]. @@ -9199,7 +9086,6 @@ SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); SQLITE_API void sqlite3_str_reset(sqlite3_str*); -SQLITE_API void sqlite3_str_truncate(sqlite3_str*,int N); /* ** CAPI3REF: Status Of A Dynamic String @@ -11033,9 +10919,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** a variable pointed to by the "pOut" parameter. ** ** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX +** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX ** is specified, then status information is available for all elements -** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If +** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If ** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements ** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of ** the EXPLAIN QUERY PLAN output) are available. Invoking API @@ -11049,8 +10935,7 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** elements used to implement the statement - a non-zero value is returned and ** the variable that pOut points to is unchanged. ** -** See also: [sqlite3_stmt_scanstatus_reset()] and the -** [nexec and ncycle] columnes of the [bytecode virtual table]. +** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ @@ -11592,41 +11477,19 @@ SQLITE_API int sqlite3_deserialize( /* ** CAPI3REF: Bind array values to the CARRAY table-valued function ** -** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to -** parameter that is the first argument of the [carray() table-valued function]. -** The S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. I must be the index of the -** parameter that is the first argument to the carray() table-valued function. -** P is a pointer to the array to be bound, and N is the number of elements in -** the array. The F argument is one of constants [SQLITE_CARRAY_INT32], -** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], -** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P. -** -** If the X argument is not a NULL pointer or one of the special -** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke -** the function X with argument D when it is finished using the data in P. -** The call to X(D) is a destructor for the array P. The destructor X(D) -** is invoked even if the call to sqlite3_carray_bind() fails. If the X -** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes -** that the data static and the destructor is never invoked. If the X -** parameter is the special-case value [SQLITE_TRANSIENT], then -** sqlite3_carray_bind_v2() makes its own private copy of the data prior -** to returning and never invokes the destructor X. -** -** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2() -** with a D parameter set to P. In other words, -** sqlite3_carray_bind(S,I,P,N,F,X) is same as -** sqlite3_carray_bind(S,I,P,N,F,X,P). -*/ -SQLITE_API int sqlite3_carray_bind_v2( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*), /* Destructor for aData */ - void *pDel /* Optional argument to xDel() */ -); +** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to +** one of the first argument of the [carray() table-valued function]. The +** S parameter is a pointer to the [prepared statement] that uses the carray() +** functions. I is the parameter index to be bound. P is a pointer to the +** array to be bound, and N is the number of eements in the array. The +** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], +** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to +** indicate the datatype of the array being bound. The X argument is not a +** NULL pointer, then SQLite will invoke the function X on the P parameter +** after it has finished using P, even if the call to +** sqlite3_carray_bind() fails. The special-case finalizer +** SQLITE_TRANSIENT has no effect here. +*/ SQLITE_API int sqlite3_carray_bind( sqlite3_stmt *pStmt, /* Statement to be bound */ int i, /* Parameter index */ @@ -14527,42 +14390,21 @@ struct fts5_api { ** It used to be the case that setting this value to zero would ** turn the limit off. That is no longer true. It is not possible ** to turn this limit off. -** -** The hard limit is the largest possible 32-bit signed integer less -** 1024, or 2147482624. */ #ifndef SQLITE_MAX_SQL_LENGTH # define SQLITE_MAX_SQL_LENGTH 1000000000 #endif /* -** The maximum depth of an expression tree. The expression tree depth -** is also limited indirectly by SQLITE_MAX_SQL_LENGTH and by -** SQLITE_MAX_PARSER_DEPTH. Reducing the maximum complexity of -** expressions can help prevent excess memory usage by hostile SQL. -** -** A value of 0 for this compile-time option causes all expression -** depth limiting code to be omitted. +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. A value of 0 means that there is no limit. */ #ifndef SQLITE_MAX_EXPR_DEPTH # define SQLITE_MAX_EXPR_DEPTH 1000 #endif -/* -** The maximum depth of the LALR(1) stack used in the parser that -** interprets SQL inputs. The parser stack depth can also be limited -** indirectly by SQLITE_MAX_SQL_LENGTH. Limiting the parser stack -** depth can help prevent excess memory usage and excess CPU stack -** usage when processing hostile SQL. -** -** Prior to version 3.45.0 (2024-01-15), the parser stack was -** hard-coded to 100 entries, and that worked fine for almost all -** applications. So the upper bound on this limit need not be large. -*/ -#ifndef SQLITE_MAX_PARSER_DEPTH -# define SQLITE_MAX_PARSER_DEPTH 2500 -#endif - /* ** The maximum number of terms in a compound SELECT statement. ** The code generator for compound SELECT statements does one @@ -15448,7 +15290,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); # define float sqlite_int64 # define fabs(X) ((X)<0?-(X):(X)) # define sqlite3IsOverflow(X) 0 -# define INFINITY (9223372036854775807LL) # ifndef SQLITE_BIG_DBL # define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) # endif @@ -15858,7 +15699,6 @@ typedef INT16_TYPE LogEst; #else # define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0) #endif -#define TWO_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&1)==0) /* ** Disable MMAP on platforms where it is known to not work @@ -17671,7 +17511,7 @@ typedef struct VdbeOpList VdbeOpList; ** Additional non-public SQLITE_PREPARE_* flags */ #define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */ -#define SQLITE_PREPARE_MASK 0x3f /* Mask of public flags */ +#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */ /* ** Prototypes for the VDBE interface. See comments on the implementation @@ -17953,10 +17793,10 @@ struct PgHdr { PCache *pCache; /* PRIVATE: Cache that owns this page */ PgHdr *pDirty; /* Transient list of dirty sorted by pgno */ Pager *pPager; /* The pager this page is part of */ + Pgno pgno; /* Page number for this page */ #ifdef SQLITE_CHECK_PAGES - u64 pageHash; /* Hash of page content */ + u32 pageHash; /* Hash of page content */ #endif - Pgno pgno; /* Page number for this page */ u16 flags; /* PGHDR flags defined below */ /********************************************************************** @@ -18296,7 +18136,7 @@ struct Schema { ** The number of different kinds of things that can be limited ** using the sqlite3_limit() interface. */ -#define SQLITE_N_LIMIT (SQLITE_LIMIT_PARSER_DEPTH+1) +#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1) /* ** Lookaside malloc is a set of fixed-size buffers that can be used @@ -18450,7 +18290,6 @@ struct sqlite3 { u8 noSharedCache; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ u8 eOpenState; /* Current condition of the connection */ - u8 nFpDigit; /* Significant digits to keep on double->text */ int nextPagesize; /* Pagesize after VACUUM if >0 */ i64 nChange; /* Value returned by sqlite3_changes() */ i64 nTotalChange; /* Value returned by sqlite3_total_changes() */ @@ -20345,6 +20184,19 @@ struct Upsert { /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. +** +** See the header comment on the computeLimitRegisters() routine for a +** detailed description of the meaning of the iLimit and iOffset fields. +** +** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes. +** These addresses must be stored so that we can go back and fill in +** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor +** the number of columns in P2 can be computed at the same time +** as the OP_OpenEphm instruction is coded because not +** enough information about the compound query is known at that point. +** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences +** for the result set. The KeyInfo for addrOpenEphm[2] contains collating +** sequences for the ORDER BY clause. */ struct Select { u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ @@ -20352,6 +20204,7 @@ struct Select { u32 selFlags; /* Various SF_* values */ int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ u32 selId; /* Unique identifier number for this SELECT */ + int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */ ExprList *pEList; /* The fields of the result */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ @@ -20383,7 +20236,7 @@ struct Select { #define SF_Resolved 0x0000004 /* Identifiers have been resolved */ #define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */ #define SF_HasAgg 0x0000010 /* Contains aggregate functions */ -#define SF_ClonedRhsIn 0x0000020 /* Cloned RHS of an IN operator */ +#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */ #define SF_Compound 0x0000100 /* Part of a compound query */ @@ -20393,14 +20246,14 @@ struct Select { #define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */ #define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */ #define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */ -/* 0x0008000 // available for reuse */ +#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */ #define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */ #define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */ #define SF_ComplexResult 0x0040000 /* Result contains subquery or function */ #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ -/* 0x0400000 // available for reuse */ +#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */ #define SF_PushDown 0x1000000 /* Modified by WHERE-clause push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ @@ -20420,6 +20273,11 @@ struct Select { ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** +** SRT_Union Store results as a key in a temporary index +** identified by pDest->iSDParm. +** +** SRT_Except Remove results from the temporary index pDest->iSDParm. +** ** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result ** set is not empty. ** @@ -20483,28 +20341,30 @@ struct Select { ** table. (pDest->iSDParm) is the number of key columns in ** each index record in this case. */ -#define SRT_Exists 1 /* Store 1 if the result is not empty */ -#define SRT_Discard 2 /* Do not save the results anywhere */ -#define SRT_DistFifo 3 /* Like SRT_Fifo, but unique results only */ -#define SRT_DistQueue 4 /* Like SRT_Queue, but unique results only */ +#define SRT_Union 1 /* Store result as keys in an index */ +#define SRT_Except 2 /* Remove result from a UNION index */ +#define SRT_Exists 3 /* Store 1 if the result is not empty */ +#define SRT_Discard 4 /* Do not save the results anywhere */ +#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */ +#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */ /* The DISTINCT clause is ignored for all of the above. Not that ** IgnorableDistinct() implies IgnorableOrderby() */ #define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue) -#define SRT_Queue 5 /* Store result in an queue */ -#define SRT_Fifo 6 /* Store result as data with an automatic rowid */ +#define SRT_Queue 7 /* Store result in an queue */ +#define SRT_Fifo 8 /* Store result as data with an automatic rowid */ /* The ORDER BY clause is ignored for all of the above */ #define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo) -#define SRT_Output 7 /* Output each row of result */ -#define SRT_Mem 8 /* Store result in a memory cell */ -#define SRT_Set 9 /* Store results as keys in an index */ -#define SRT_EphemTab 10 /* Create transient tab and store like SRT_Table */ -#define SRT_Coroutine 11 /* Generate a single row of result */ -#define SRT_Table 12 /* Store result as data with an automatic rowid */ -#define SRT_Upfrom 13 /* Store result as data with rowid */ +#define SRT_Output 9 /* Output each row of result */ +#define SRT_Mem 10 /* Store result in a memory cell */ +#define SRT_Set 11 /* Store results as keys in an index */ +#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */ +#define SRT_Coroutine 13 /* Generate a single row of result */ +#define SRT_Table 14 /* Store result as data with an automatic rowid */ +#define SRT_Upfrom 15 /* Store result as data with rowid */ /* ** An instance of this object describes where to put of the results of @@ -20640,12 +20500,17 @@ struct Parse { u8 nested; /* Number of nested calls to the parser/code generator */ u8 nTempReg; /* Number of temporary registers in aTempReg[] */ u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ + u8 mayAbort; /* True if statement may throw an ABORT exception */ + u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ + u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ + u8 bReturning; /* Coding a RETURNING trigger */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ + u8 disableTriggers; /* True to disable triggers */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif @@ -20654,15 +20519,10 @@ struct Parse { u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER) ** and ALTER TABLE ADD COLUMN. */ #endif - bft disableTriggers:1; /* True to disable triggers */ - bft mayAbort :1; /* True if statement may throw an ABORT exception */ - bft hasCompound :1; /* Need to invoke convertCompoundSelectToSubquery() */ - bft bReturning :1; /* Coding a RETURNING trigger */ - bft bHasExists :1; /* Has a correlated "EXISTS (SELECT ....)" expression */ - bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ - bft bHasWith :1; /* True if statement contains WITH */ - bft okConstFactor:1; /* OK to factor out constants */ - bft checkSchema :1; /* Causes schema cookie check after an error */ + bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */ + bft bHasWith :1; /* True if statement contains WITH */ + bft okConstFactor :1; /* OK to factor out constants */ + bft checkSchema :1; /* Causes schema cookie check after an error */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ @@ -20891,19 +20751,19 @@ struct Trigger { ** orconf -> stores the ON CONFLICT algorithm ** pSelect -> The content to be inserted - either a SELECT statement or ** a VALUES clause. -** pSrc -> Table to insert into. +** zTarget -> Dequoted name of the table to insert into. ** pIdList -> If this is an INSERT INTO ... () VALUES ... ** statement, then this stores the column-names to be ** inserted into. ** pUpsert -> The ON CONFLICT clauses for an Upsert ** ** (op == TK_DELETE) -** pSrc -> Table to delete from +** zTarget -> Dequoted name of the table to delete from. ** pWhere -> The WHERE clause of the DELETE statement if one is specified. ** Otherwise NULL. ** ** (op == TK_UPDATE) -** pSrc -> Table to update, followed by any FROM clause tables. +** zTarget -> Dequoted name of the table to update. ** pWhere -> The WHERE clause of the UPDATE statement if one is specified. ** Otherwise NULL. ** pExprList -> A list of the columns to update and the expressions to update @@ -20923,7 +20783,8 @@ struct TriggerStep { u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ - SrcList *pSrc; /* Table to insert/update/delete */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ + SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */ IdList *pIdList; /* Column names for INSERT */ @@ -21006,11 +20867,10 @@ typedef struct { /* ** Allowed values for mInitFlags */ -#define INITFLAG_AlterMask 0x0007 /* Types of ALTER */ +#define INITFLAG_AlterMask 0x0003 /* Types of ALTER */ #define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */ #define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */ #define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */ -#define INITFLAG_AlterDropCons 0x0004 /* Reparse after an ADD COLUMN */ /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning @@ -21140,7 +21000,6 @@ struct Walker { NameContext *pNC; /* Naming context */ int n; /* A counter */ int iCur; /* A cursor number */ - int sz; /* String literal length */ SrcList *pSrcList; /* FROM clause */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */ @@ -21545,20 +21404,7 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*); SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void); SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void); - -/* The SQLITE_THREAD_MISUSE_WARNINGS compile-time option used to be called -** SQLITE_ENABLE_MULTITHREADED_CHECKS. Keep that older macro for backwards -** compatibility, at least for a while... */ -#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS -# define SQLITE_THREAD_MISUSE_WARNINGS 1 -#endif - -/* SQLITE_THREAD_MISUSE_ABORT implies SQLITE_THREAD_MISUSE_WARNINGS */ -#ifdef SQLITE_THREAD_MISUSE_ABORT -# define SQLITE_THREAD_MISUSE_WARNINGS 1 -#endif - -#if defined(SQLITE_THREAD_MISUSE_WARNINGS) && !defined(SQLITE_MUTEX_OMIT) +#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT) SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*); #else # define sqlite3MutexWarnOnContention(x) @@ -21592,12 +21438,12 @@ struct PrintfArguments { ** value into an approximate decimal representation. */ struct FpDecode { + char sign; /* '+' or '-' */ + char isSpecial; /* 1: Infinity 2: NaN */ int n; /* Significant digits in the decode */ int iDP; /* Location of the decimal point */ char *z; /* Start of significant digits */ - char zBuf[20]; /* Storage for significant digits */ - char sign; /* '+' or '-' */ - char isSpecial; /* 1: Infinity 2: NaN */ + char zBuf[24]; /* Storage for significant digits */ }; SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int); @@ -21686,7 +21532,6 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int); #endif SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); -SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3*,int); SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); @@ -21938,7 +21783,6 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*); SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); -SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr*); SQLITE_PRIVATE int sqlite3IsRowid(const char*); SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab); SQLITE_PRIVATE void sqlite3GenerateRowDelete( @@ -22007,16 +21851,17 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,SrcList*, IdList*, +SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*, Select*,u8,Upsert*, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,SrcList*,SrcList*,ExprList*, +SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*, Expr*, u8, const char*,const char*); -SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,SrcList*, Expr*, +SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*, const char*,const char*); SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); +SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*); # define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p)) # define sqlite3IsToplevel(p) ((p)->pToplevel==0) #else @@ -22030,6 +21875,7 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Tab # define sqlite3ParseToplevel(p) p # define sqlite3IsToplevel(p) 1 # define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0 +# define sqlite3TriggerStepSrc(A,B) 0 #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); @@ -22062,7 +21908,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*); SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64); SQLITE_PRIVATE i64 sqlite3RealToI64(double); SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*); -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*); +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8); SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*); SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*); SQLITE_PRIVATE int sqlite3Atoi(const char*); @@ -22206,13 +22052,10 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); -SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*); -SQLITE_PRIVATE void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int); -SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); -SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int); +SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*); SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*); SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*); @@ -24627,7 +24470,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*)); -SQLITE_PRIVATE int sqlite3VdbeMemSetText(Mem*, const char*, i64, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 @@ -24646,14 +24488,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); -SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem*); +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); -SQLITE_PRIVATE SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem*, int*); SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); @@ -25613,7 +25454,7 @@ static int parseDateOrTime( return 0; }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){ return setDateTimeToCurrent(context, p); - }else if( sqlite3AtoF(zDate, &r)>0 ){ + }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){ setRawDateNumber(p, r); return 0; }else if( (sqlite3StrICmp(zDate,"subsec")==0 @@ -26059,7 +25900,7 @@ static int parseModifier( ** date is already on the appropriate weekday, this is a no-op. */ if( sqlite3_strnicmp(z, "weekday ", 8)==0 - && sqlite3AtoF(&z[8], &r)>0 + && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0 && r>=0.0 && r<7.0 && (n=(int)r)==r ){ sqlite3_int64 Z; computeYMD_HMS(p); @@ -26130,11 +25971,9 @@ static int parseModifier( case '8': case '9': { double rRounder; - int i, rx; + int i; int Y,M,D,h,m,x; const char *z2 = z; - char *zCopy; - sqlite3 *db = sqlite3_context_db_handle(pCtx); char z0 = z[0]; for(n=1; z[n]; n++){ if( z[n]==':' ) break; @@ -26144,11 +25983,7 @@ static int parseModifier( if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break; } } - zCopy = sqlite3DbStrNDup(db, z, n); - if( zCopy==0 ) break; - rx = sqlite3AtoF(zCopy, &r)<=0; - sqlite3DbFree(db, zCopy); - if( rx ){ + if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){ assert( rc==1 ); break; } @@ -26968,7 +26803,7 @@ static void datedebugFunc( char *zJson; zJson = sqlite3_mprintf( "{iJD:%lld,Y:%d,M:%d,D:%d,h:%d,m:%d,tz:%d," - "s:%.3f,validJD:%d,validYMD:%d,validHMS:%d," + "s:%.3f,validJD:%d,validYMS:%d,validHMS:%d," "nFloor:%d,rawS:%d,isError:%d,useSubsec:%d," "isUtc:%d,isLocal:%d}", x.iJD, x.Y, x.M, x.D, x.h, x.m, x.tz, @@ -29747,28 +29582,23 @@ static SQLITE_WSD int mutexIsInit = 0; #ifndef SQLITE_MUTEX_OMIT -#ifdef SQLITE_THREAD_MISUSE_WARNINGS +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS /* -** This block (enclosed by SQLITE_THREAD_MISUSE_WARNINGS) contains +** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains ** the implementation of a wrapper around the system default mutex ** implementation (sqlite3DefaultMutex()). ** ** Most calls are passed directly through to the underlying default ** mutex implementation. Except, if a mutex is configured by calling ** sqlite3MutexWarnOnContention() on it, then if contention is ever -** encountered within xMutexEnter() then a warning is emitted via -** sqlite3_log(). Furthermore, if SQLITE_THREAD_MISUSE_ABORT is -** defined then abort() is called after the sqlite3_log() warning. +** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). ** -** This type of mutex is used on the database handle mutex when testing -** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. A failure -** indicates that the app ought to be using SQLITE_OPEN_FULLMUTEX or -** similar because it is trying to use the same database handle from -** two different connections at the same time. +** This type of mutex is used as the database handle mutex when testing +** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. */ /* -** Type for all mutexes used when SQLITE_THREAD_MISUSE_WARNINGS +** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS ** is defined. Variable CheckMutex.mutex is a pointer to the real mutex ** allocated by the system mutex implementation. Variable iType is usually set ** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST @@ -29804,12 +29634,11 @@ static int checkMutexNotheld(sqlite3_mutex *p){ */ static int checkMutexInit(void){ pGlobalMutexMethods = sqlite3DefaultMutex(); - return pGlobalMutexMethods->xMutexInit(); + return SQLITE_OK; } static int checkMutexEnd(void){ - int rc = pGlobalMutexMethods->xMutexEnd(); pGlobalMutexMethods = 0; - return rc; + return SQLITE_OK; } /* @@ -29886,9 +29715,6 @@ static void checkMutexEnter(sqlite3_mutex *p){ sqlite3_log(SQLITE_MISUSE, "illegal multi-threaded access to database connection" ); -#if SQLITE_THREAD_MISUSE_ABORT - abort(); -#endif } pGlobalMutexMethods->xMutexEnter(pCheck->mutex); } @@ -29940,7 +29766,7 @@ SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION; } } -#endif /* ifdef SQLITE_THREAD_MISUSE_WARNINGS */ +#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ /* ** Initialize the mutex system. @@ -29957,7 +29783,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){ sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; if( sqlite3GlobalConfig.bCoreMutex ){ -#ifdef SQLITE_THREAD_MISUSE_WARNINGS +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS pFrom = multiThreadedCheckMutex(); #else pFrom = sqlite3DefaultMutex(); @@ -30805,6 +30631,14 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ # define SQLITE_OS_WINCE 0 #endif +/* +** Determine if we are dealing with WinRT, which provides only a subset of +** the full Win32 API. +*/ +#if !defined(SQLITE_OS_WINRT) +# define SQLITE_OS_WINRT 0 +#endif + /* ** For WinCE, some API function parameters do not appear to be declared as ** volatile. @@ -30819,7 +30653,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ ** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() ** functions are not available (e.g. those not using MSVC, Cygwin, etc). */ -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && \ +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) # define SQLITE_OS_WIN_THREADS 1 #else @@ -30936,7 +30770,11 @@ static int winMutexInit(void){ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ int i; for(i=0; itrace = 1; #endif #endif +#if SQLITE_OS_WINRT + InitializeCriticalSectionEx(&p->mutex, 0, 0); +#else InitializeCriticalSection(&p->mutex); +#endif } break; } @@ -32651,7 +32493,7 @@ SQLITE_API void sqlite3_str_vappendf( }else{ iRound = precision+1; } - sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16); + sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16); if( s.isSpecial ){ if( s.isSpecial==2 ){ bufpt = flag_zeropad ? "null" : "NaN"; @@ -33330,14 +33172,6 @@ SQLITE_API int sqlite3_str_length(sqlite3_str *p){ return p ? p->nChar : 0; } -/* Truncate the text of the string to be no more than N bytes. */ -SQLITE_API void sqlite3_str_truncate(sqlite3_str *p, int N){ - if( p!=0 && N>=0 && (u32)NnChar ){ - p->nChar = N; - p->zText[p->nChar] = 0; - } -} - /* Return the current value for p */ SQLITE_API char *sqlite3_str_value(sqlite3_str *p){ if( p==0 || p->nChar==0 ) return 0; @@ -33358,17 +33192,6 @@ SQLITE_API void sqlite3_str_reset(StrAccum *p){ p->zText = 0; } -/* -** Destroy a dynamically allocate sqlite3_str object and all -** of its content, all in one call. -*/ -SQLITE_API void sqlite3_str_free(sqlite3_str *p){ - if( p ){ - sqlite3_str_reset(p); - sqlite3_free(p); - } -} - /* ** Initialize a string accumulator. ** @@ -34982,13 +34805,7 @@ SQLITE_PRIVATE void sqlite3TreeViewTrigger( SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); } SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);} SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); } -SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ - TreeView *pView = 0; - sqlite3TreeViewPush(&pView, 0); - sqlite3TreeViewLine(pView, "SRCLIST"); - sqlite3TreeViewSrcList(pView,p); - sqlite3TreeViewPop(&pView); -} +SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); } SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); } SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); } SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); } @@ -36508,262 +36325,48 @@ SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){ return h; } -/* -** Two inputs are multiplied to get a 128-bit result. Return -** the high-order 64 bits of that result. -*/ -static u64 sqlite3Multiply128(u64 a, u64 b){ -#if (defined(__GNUC__) || defined(__clang__)) \ - && (defined(__x86_64__) || defined(__aarch64__) || defined(__riscv)) - return ((__uint128_t)a * b) >> 64; -#elif defined(_MSC_VER) && defined(_M_X64) - return __umulh(a, b); -#else - u64 a1 = (u32)a; - u64 a2 = a >> 32; - u64 b1 = (u32)b; - u64 b2 = b >> 32; - u64 p0 = a1 * b1; - u64 p1 = a1 * b2; - u64 p2 = a2 * b1; - u64 p3 = a2 * b2; - u64 carry = ((p0 >> 32) + (u32)p1 + (u32)p2) >> 32; - return p3 + (p1 >> 32) + (p2 >> 32) + carry; -#endif -} - -/* -** Return a u64 with the N-th bit set. -*/ -#define U64_BIT(N) (((u64)1)<<(N)) - -/* -** Range of powers of 10 that we need to deal with when converting -** IEEE754 doubles to and from decimal. -*/ -#define POWERSOF10_FIRST (-348) -#define POWERSOF10_LAST (+347) - -/* -** For any p between -348 and +347, return the integer part of -** -** pow(10,p) * pow(2,63-pow10to2(p)) -** -** Or, in other words, for any p in range, return the most significant -** 64 bits of pow(10,p). The pow(10,p) value is shifted left or right, -** as appropriate so the most significant 64 bits fit exactly into a -** 64-bit unsigned integer. -** -** Algorithm: -** -** (1) For p between 0 and 26, return the value directly from the aBase[] -** lookup table. -** -** (2) For p outside the range 0 to 26, use aScale[] for the initial value -** then refine that result (if necessary) by a single multiplication -** against aBase[]. -*/ -static u64 powerOfTen(int p){ - static const u64 aBase[] = { - 0x8000000000000000LLU, /* 0: 1.0e+0 << 63 */ - 0xa000000000000000LLU, /* 1: 1.0e+1 << 60 */ - 0xc800000000000000LLU, /* 2: 1.0e+2 << 57 */ - 0xfa00000000000000LLU, /* 3: 1.0e+3 << 54 */ - 0x9c40000000000000LLU, /* 4: 1.0e+4 << 50 */ - 0xc350000000000000LLU, /* 5: 1.0e+5 << 47 */ - 0xf424000000000000LLU, /* 6: 1.0e+6 << 44 */ - 0x9896800000000000LLU, /* 7: 1.0e+7 << 40 */ - 0xbebc200000000000LLU, /* 8: 1.0e+8 << 37 */ - 0xee6b280000000000LLU, /* 9: 1.0e+9 << 34 */ - 0x9502f90000000000LLU, /* 10: 1.0e+10 << 30 */ - 0xba43b74000000000LLU, /* 11: 1.0e+11 << 27 */ - 0xe8d4a51000000000LLU, /* 12: 1.0e+12 << 24 */ - 0x9184e72a00000000LLU, /* 13: 1.0e+13 << 20 */ - 0xb5e620f480000000LLU, /* 14: 1.0e+14 << 17 */ - 0xe35fa931a0000000LLU, /* 15: 1.0e+15 << 14 */ - 0x8e1bc9bf04000000LLU, /* 16: 1.0e+16 << 10 */ - 0xb1a2bc2ec5000000LLU, /* 17: 1.0e+17 << 7 */ - 0xde0b6b3a76400000LLU, /* 18: 1.0e+18 << 4 */ - 0x8ac7230489e80000LLU, /* 19: 1.0e+19 >> 0 */ - 0xad78ebc5ac620000LLU, /* 20: 1.0e+20 >> 3 */ - 0xd8d726b7177a8000LLU, /* 21: 1.0e+21 >> 6 */ - 0x878678326eac9000LLU, /* 22: 1.0e+22 >> 10 */ - 0xa968163f0a57b400LLU, /* 23: 1.0e+23 >> 13 */ - 0xd3c21bcecceda100LLU, /* 24: 1.0e+24 >> 16 */ - 0x84595161401484a0LLU, /* 25: 1.0e+25 >> 20 */ - 0xa56fa5b99019a5c8LLU, /* 26: 1.0e+26 >> 23 */ - }; - static const u64 aScale[] = { - 0x8049a4ac0c5811aeLLU, /* 0: 1.0e-351 << 1229 */ - 0xcf42894a5dce35eaLLU, /* 1: 1.0e-324 << 1140 */ - 0xa76c582338ed2622LLU, /* 2: 1.0e-297 << 1050 */ - 0x873e4f75e2224e68LLU, /* 3: 1.0e-270 << 960 */ - 0xda7f5bf590966849LLU, /* 4: 1.0e-243 << 871 */ - 0xb080392cc4349dedLLU, /* 5: 1.0e-216 << 781 */ - 0x8e938662882af53eLLU, /* 6: 1.0e-189 << 691 */ - 0xe65829b3046b0afaLLU, /* 7: 1.0e-162 << 602 */ - 0xba121a4650e4ddecLLU, /* 8: 1.0e-135 << 512 */ - 0x964e858c91ba2655LLU, /* 9: 1.0e-108 << 422 */ - 0xf2d56790ab41c2a3LLU, /* 10: 1.0e-81 << 333 */ - 0xc428d05aa4751e4dLLU, /* 11: 1.0e-54 << 243 */ - 0x9e74d1b791e07e48LLU, /* 12: 1.0e-27 << 153 */ - 0x8000000000000000LLU, /* 13: 1.0e+0 << 63 */ - 0xcecb8f27f4200f3aLLU, /* 14: 1.0e+27 >> 26 */ - 0xa70c3c40a64e6c52LLU, /* 15: 1.0e+54 >> 116 */ - 0x86f0ac99b4e8dafdLLU, /* 16: 1.0e+81 >> 206 */ - 0xda01ee641a708deaLLU, /* 17: 1.0e+108 >> 295 */ - 0xb01ae745b101e9e4LLU, /* 18: 1.0e+135 >> 385 */ - 0x8e41ade9fbebc27dLLU, /* 19: 1.0e+162 >> 475 */ - 0xe5d3ef282a242e82LLU, /* 20: 1.0e+189 >> 564 */ - 0xb9a74a0637ce2ee1LLU, /* 21: 1.0e+216 >> 654 */ - 0x95f83d0a1fb69cd9LLU, /* 22: 1.0e+243 >> 744 */ - 0xf24a01a73cf2dcd0LLU, /* 23: 1.0e+270 >> 833 */ - 0xc3b8358109e84f07LLU, /* 24: 1.0e+297 >> 923 */ - 0x9e19db92b4e31ba9LLU, /* 25: 1.0e+324 >> 1013 */ - }; - int g, n; - u64 x, y; - - assert( p>=POWERSOF10_FIRST && p<=POWERSOF10_LAST ); - if( p<0 ){ - g = p/27; - n = p%27; - if( n ){ - g--; - n += 27; - } - }else if( p<27 ){ - return aBase[p]; - }else{ - g = p/27; - n = p%27; - } - y = aScale[g+13]; - if( n==0 ){ - return y; - } - x = sqlite3Multiply128(aBase[n],y); - if( (U64_BIT(63) & x)==0 ){ - x = (x<<1)|1; - } - return x; -} - -/* -** pow10to2(x) computes floor(log2(pow(10,x))). -** pow2to10(y) computes floor(log10(pow(2,y))). -** -** Conceptually, pow10to2(p) converts a base-10 exponent p into -** a corresponding base-2 exponent, and pow2to10(e) converts a base-2 -** exponent into a base-10 exponent. -** -** The conversions are based on the observation that: -** -** ln(10.0)/ln(2.0) == 108853/32768 (approximately) -** ln(2.0)/ln(10.0) == 78913/262144 (approximately) -** -** These ratios are approximate, but they are accurate to 5 digits, -** which is close enough for the usage here. Right-shift is used -** for division so that rounding of negative numbers happens in the -** right direction. -*/ -static int pwr10to2(int p){ return (p*108853) >> 15; } -static int pwr2to10(int p){ return (p*78913) >> 18; } - -/* -** Count leading zeros for a 64-bit unsigned integer. -*/ -static int countLeadingZeros(u64 m){ -#if defined(__GNUC__) || defined(__clang__) - return __builtin_clzll(m); -#else - int n = 0; - if( m <= 0x00000000ffffffffULL) { n += 32; m <<= 32; } - if( m <= 0x0000ffffffffffffULL) { n += 16; m <<= 16; } - if( m <= 0x00ffffffffffffffULL) { n += 8; m <<= 8; } - if( m <= 0x0fffffffffffffffULL) { n += 4; m <<= 4; } - if( m <= 0x3fffffffffffffffULL) { n += 2; m <<= 2; } - if( m <= 0x7fffffffffffffffULL) { n += 1; } - return n; -#endif -} - -/* -** Given m and e, which represent a quantity r == m*pow(2,e), -** return values *pD and *pP such that r == (*pD)*pow(10,*pP), -** approximately. *pD should contain at least n significant digits. +/* Double-Double multiplication. (x[0],x[1]) *= (y,yy) ** -** The input m is required to have its highest bit set. In other words, -** m should be left-shifted, and e decremented, to maximize the value of m. -*/ -static void sqlite3Fp2Convert10(u64 m, int e, int n, u64 *pD, int *pP){ - int p; - u64 h; - assert( n>=1 && n<=18 ); - p = n - 1 - pwr2to10(e+63); - h = sqlite3Multiply128(m, powerOfTen(p)); - assert( -(e + pwr10to2(p) + 2) >= 0 ); - assert( -(e + pwr10to2(p) + 1) <= 63 ); - if( n==18 ){ - h >>= -(e + pwr10to2(p) + 2); - *pD = (h + ((h<<1)&2))>>1; - }else{ - *pD = h >> -(e + pwr10to2(p) + 1); - } - *pP = -p; -} - -/* -** Return an IEEE754 floating point value that approximates d*pow(10,p). +** Reference: +** T. J. Dekker, "A Floating-Point Technique for Extending the +** Available Precision". 1971-07-26. */ -static double sqlite3Fp10Convert2(u64 d, int p){ - u64 out; - int e1; - int lz; - int lp; - int x; - u64 h; - double r; - assert( (d & U64_BIT(63))==0 ); - assert( d!=0 ); - if( pPOWERSOF10_LAST ){ - return INFINITY; - } - lz = countLeadingZeros(d); - lp = pwr10to2(p); - e1 = lz - (lp + 11); - if( e1>1074 ){ - if( e1>=1130 ) return 0.0; - e1 = 1074; - } - h = sqlite3Multiply128(d<= 0 ); - assert( x <= 63 ); - out = h >> x; - if( out >= U64_BIT(55)-2 ){ - out >>= 1; - e1--; - } - if( e1<=(-972) ){ - return INFINITY; - } - out = (out + 2) >> 2; - if( (out & U64_BIT(52))!=0 ){ - out = (out & ~U64_BIT(52)) | ((u64)(1075-e1)<<52); - } - memcpy(&r, &out, 8); - return r; +static void dekkerMul2(volatile double *x, double y, double yy){ + /* + ** The "volatile" keywords on parameter x[] and on local variables + ** below are needed force intermediate results to be truncated to + ** binary64 rather than be carried around in an extended-precision + ** format. The truncation is necessary for the Dekker algorithm to + ** work. Intel x86 floating point might omit the truncation without + ** the use of volatile. + */ + volatile double tx, ty, p, q, c, cc; + double hx, hy; + u64 m; + memcpy(&m, (void*)&x[0], 8); + m &= 0xfffffffffc000000LL; + memcpy(&hx, &m, 8); + tx = x[0] - hx; + memcpy(&m, &y, 8); + m &= 0xfffffffffc000000LL; + memcpy(&hy, &m, 8); + ty = y - hy; + p = hx*hy; + q = hx*ty + tx*hy; + c = p+q; + cc = p - c + q + tx*ty; + cc = x[0]*yy + x[1]*y + cc; + x[0] = c + cc; + x[1] = c - x[0]; + x[1] += cc; } /* ** The string z[] is an text representation of a real number. ** Convert this string to a double and write it into *pResult. ** -** z[] must be UTF-8 and zero-terminated. +** The string z[] is length bytes in length (bytes, not characters) and +** uses the encoding enc. The string is not necessarily zero-terminated. ** ** Return TRUE if the result is a valid real number (or integer) and FALSE ** if the string is empty or contains extraneous text. More specifically @@ -36790,131 +36393,198 @@ static double sqlite3Fp10Convert2(u64 d, int p){ #if defined(_MSC_VER) #pragma warning(disable : 4756) #endif -SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){ +SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT + int incr; + const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ - int neg = 0; /* True for a negative value */ - u64 s = 0; /* mantissa */ - int d = 0; /* Value is s * pow(10,d) */ + int sign = 1; /* sign of significand */ + u64 s = 0; /* significand */ + int d = 0; /* adjust exponent for shifting decimal point */ + int esign = 1; /* sign of exponent */ + int e = 0; /* exponent */ + int eValid = 1; /* True exponent is either not used or is well-formed */ int nDigit = 0; /* Number of digits processed */ - int eType = 1; /* 1: pure integer, 2+: fractional */ + int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */ + u64 s2; /* round-tripped significand */ + double rr[2]; + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ + if( length==0 ) return 0; + + if( enc==SQLITE_UTF8 ){ + incr = 1; + zEnd = z + length; + }else{ + int i; + incr = 2; + length &= ~1; + assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + testcase( enc==SQLITE_UTF16LE ); + testcase( enc==SQLITE_UTF16BE ); + for(i=3-enc; i=zEnd ) return 0; /* get sign of significand */ if( *z=='-' ){ - neg = 1; - z++; + sign = -1; + z+=incr; }else if( *z=='+' ){ - z++; + z+=incr; } /* copy max significant digits to significand */ - while( sqlite3Isdigit(*z) ){ + while( z=((LARGEST_INT64-9)/10) ){ + z+=incr; nDigit++; + if( s>=((LARGEST_UINT64-9)/10) ){ /* skip non-significant significand digits ** (increase exponent by d to shift decimal left) */ - while( sqlite3Isdigit(*z) ){ z++; d++; } + while( z=zEnd ) goto do_atof_calc; /* if decimal point is present */ if( *z=='.' ){ - z++; + z+=incr; eType++; /* copy digits from after decimal to significand ** (decrease exponent by d to shift decimal right) */ - while( sqlite3Isdigit(*z) ){ - if( s<((LARGEST_INT64-9)/10) ){ + while( z=zEnd ) goto do_atof_calc; /* if exponent is present */ if( *z=='e' || *z=='E' ){ - int esign = 1; /* sign of exponent */ - z++; + z+=incr; + eValid = 0; eType++; + /* This branch is needed to avoid a (harmless) buffer overread. The + ** special comment alerts the mutation tester that the correct answer + ** is obtained even if the branch is omitted */ + if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/ + /* get sign of exponent */ if( *z=='-' ){ esign = -1; - z++; + z+=incr; }else if( *z=='+' ){ - z++; + z+=incr; } /* copy digits to exponent */ - if( sqlite3Isdigit(*z) ){ - int exp = *z - '0'; - z++; - while( sqlite3Isdigit(*z) ){ - exp = exp<10000 ? (exp*10 + (*z - '0')) : 10000; - z++; - } - d += esign*exp; - }else{ - eType = -1; + while( z0 && s<((LARGEST_UINT64-0x7ff)/10) ){ + s *= 10; + e--; + } + while( e<0 && (s%10)==0 ){ + s /= 10; + e++; + } + + rr[0] = (double)s; + assert( sizeof(s2)==sizeof(rr[0]) ); +#ifdef SQLITE_DEBUG + rr[1] = 18446744073709549568.0; + memcpy(&s2, &rr[1], sizeof(s2)); + assert( s2==0x43efffffffffffffLL ); +#endif + /* Largest double that can be safely converted to u64 + ** vvvvvvvvvvvvvvvvvvvvvv */ + if( rr[0]<=18446744073709549568.0 ){ + s2 = (u64)rr[0]; + rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s); + }else{ + rr[1] = 0.0; + } + assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */ + + if( e>0 ){ + while( e>=100 ){ + e -= 100; + dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); + } + while( e>=10 ){ + e -= 10; + dekkerMul2(rr, 1.0e+10, 0.0); + } + while( e>=1 ){ + e -= 1; + dekkerMul2(rr, 1.0e+01, 0.0); + } }else{ - *pResult = sqlite3Fp10Convert2(s,d); - if( neg ) *pResult = -*pResult; - assert( !sqlite3IsNaN(*pResult) ); + while( e<=-100 ){ + e += 100; + dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); + } + while( e<=-10 ){ + e += 10; + dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); + } + while( e<=-1 ){ + e += 1; + dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); + } } + *pResult = rr[0]+rr[1]; + if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300; + if( sign<0 ) *pResult = -*pResult; + assert( !sqlite3IsNaN(*pResult) ); +atof_return: /* return true if number and no extra non-whitespace characters after */ - if( z[0]==0 && nDigit>0 ){ + if( z==zEnd && nDigit>0 && eValid && eType>0 ){ return eType; - }else if( eType>=2 && nDigit>0 ){ + }else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){ return -1; }else{ return 0; } #else - return !sqlite3Atoi64(z, pResult, strlen(z), SQLITE_UTF8); + return !sqlite3Atoi64(z, pResult, length, enc); #endif /* SQLITE_OMIT_FLOATING_POINT */ } #if defined(_MSC_VER) #pragma warning(default : 4756) #endif -/* -** Digit pairs used to convert a U64 or I64 into text, two digits -** at a time. -*/ -static const union { - char a[201]; - short int forceAlignment; -} sqlite3DigitPairs = { - "00010203040506070809" - "10111213141516171819" - "20212223242526272829" - "30313233343536373839" - "40414243444546474849" - "50515253545556575859" - "60616263646566676869" - "70717273747576777879" - "80818283848586878889" - "90919293949596979899" -}; - - /* ** Render an signed 64-bit integer as text. Store the result in zOut[] and ** return the length of the string that was stored, in bytes. The value @@ -36926,35 +36596,23 @@ static const union { SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){ int i; u64 x; - union { - char a[23]; - u16 forceAlignment; - } u; - if( v>0 ){ - x = v; - }else if( v==0 ){ - zOut[0] = '0'; - zOut[1] = 0; - return 1; - }else{ + char zTemp[22]; + if( v<0 ){ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v; + }else{ + x = v; } - i = sizeof(u.a)-1; - u.a[i] = 0; - while( x>=10 ){ - int kk = (x%100)*2; - assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) ); - assert( TWO_BYTE_ALIGNMENT(&u.a[i-2]) ); - *(u16*)(&u.a[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk]; - i -= 2; - x /= 100; - } - if( x ){ - u.a[--i] = x + '0'; - } - if( v<0 ) u.a[--i] = '-'; - memcpy(zOut, &u.a[i], sizeof(u.a)-i); - return sizeof(u.a)-1-i; + i = sizeof(zTemp)-2; + zTemp[sizeof(zTemp)-1] = 0; + while( 1 /*exit-by-break*/ ){ + zTemp[i] = (x%10) + '0'; + x = x/10; + if( x==0 ) break; + i--; + }; + if( v<0 ) zTemp[--i] = '-'; + memcpy(zOut, &zTemp[i], sizeof(zTemp)-i); + return sizeof(zTemp)-1-i; } /* @@ -37211,7 +36869,7 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ ** representation. ** ** If iRound<=0 then round to -iRound significant digits to the -** the right of the decimal point, or to a maximum of mxRound total +** the left of the decimal point, or to a maximum of mxRound total ** significant digits. ** ** If iRound>0 round to min(iRound,mxRound) significant digits total. @@ -37224,14 +36882,13 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){ ** The p->z[] array is *not* zero-terminated. */ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ - int i; /* Index into zBuf[] where to put next character */ - int n; /* Number of digits */ - u64 v; /* mantissa */ - int e, exp = 0; /* Base-2 and base-10 exponent */ - char *zBuf; /* Local alias for p->zBuf */ - char *z; /* Local alias for p->z */ + int i; + u64 v; + int e, exp = 0; + double rr[2]; p->isSpecial = 0; + p->z = p->zBuf; assert( mxRound>0 ); /* Convert negative numbers to positive. Deal with Infinity, 0.0, and @@ -37249,94 +36906,78 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou p->sign = '+'; } memcpy(&v,&r,8); - e = (v>>52)&0x7ff; - if( e==0x7ff ){ + e = v>>52; + if( (e&0x7ff)==0x7ff ){ p->isSpecial = 1 + (v!=0x7ff0000000000000LL); p->n = 0; p->iDP = 0; - p->z = p->zBuf; return; } - v &= 0x000fffffffffffffULL; - if( e==0 ){ - int nn = countLeadingZeros(v); - v <<= nn; - e = -1074 - nn; + + /* Multiply r by powers of ten until it lands somewhere in between + ** 1.0e+19 and 1.0e+17. + ** + ** Use Dekker-style double-double computation to increase the + ** precision. + ** + ** The error terms on constants like 1.0e+100 computed using the + ** decimal extension, for example as follows: + ** + ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100))); + */ + rr[0] = r; + rr[1] = 0.0; + if( rr[0]>9.223372036854774784e+18 ){ + while( rr[0]>9.223372036854774784e+118 ){ + exp += 100; + dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117); + } + while( rr[0]>9.223372036854774784e+28 ){ + exp += 10; + dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27); + } + while( rr[0]>9.223372036854774784e+18 ){ + exp += 1; + dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18); + } }else{ - v = (v<<11) | U64_BIT(63); - e -= 1086; + while( rr[0]<9.223372036854774784e-83 ){ + exp -= 100; + dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83); + } + while( rr[0]<9.223372036854774784e+07 ){ + exp -= 10; + dekkerMul2(rr, 1.0e+10, 0.0); + } + while( rr[0]<9.22337203685477478e+17 ){ + exp -= 1; + dekkerMul2(rr, 1.0e+01, 0.0); + } } - sqlite3Fp2Convert10(v, e, (iRound<=0||iRound>=18)?18:iRound+1, &v, &exp); + v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1]; - /* Extract significant digits, start at the right-most slot in p->zBuf - ** and working back to the right. "i" keeps track of the next slot in - ** which to store a digit. */ + /* Extract significant digits. */ i = sizeof(p->zBuf)-1; - zBuf = p->zBuf; assert( v>0 ); - while( v>=10 ){ - int kk = (v%100)*2; - assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) ); - assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) ); - *(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk]; - i -= 2; - v /= 100; - } - if( v ){ - assert( v<10 ); - zBuf[i--] = v + '0'; - } + while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; } assert( i>=0 && izBuf)-1 ); - n = sizeof(p->zBuf) - 1 - i; /* Total number of digits extracted */ - assert( n>0 ); - assert( nzBuf) ); - testcase( n==sizeof(p->zBuf)-1 ); - p->iDP = n + exp; + p->n = sizeof(p->zBuf) - 1 - i; + assert( p->n>0 ); + assert( p->nzBuf) ); + p->iDP = p->n + exp; if( iRound<=0 ){ iRound = p->iDP - iRound; - if( iRound==0 && zBuf[i+1]>='5' ){ + if( iRound==0 && p->zBuf[i+1]>='5' ){ iRound = 1; - zBuf[i--] = '0'; - n++; + p->zBuf[i--] = '0'; + p->n++; p->iDP++; } } - z = &zBuf[i+1]; /* z points to the first digit */ - if( iRound>0 && (iRoundmxRound) ){ + if( iRound>0 && (iRoundn || p->n>mxRound) ){ + char *z = &p->zBuf[i+1]; if( iRound>mxRound ) iRound = mxRound; - if( iRound==17 ){ - /* If the precision is exactly 17, which only happens with the "!" - ** flag (ex: "%!.17g") then try to reduce the precision if that - ** yields text that will round-trip to the original floating-point. - ** value. Thus, for exaple, 49.47 will render as 49.47, rather than - ** as 49.469999999999999. */ - if( z[15]=='9' && z[14]=='9' ){ - int jj, kk; - u64 v2; - for(jj=14; jj>0 && z[jj-1]=='9'; jj--){} - if( jj==0 ){ - v2 = 1; - }else{ - v2 = z[0] - '0'; - for(kk=1; kkiDP>=n || (z[15]=='0' && z[14]=='0' && z[13]=='0') ){ - int jj, kk; - u64 v2; - assert( z[0]!='0' ); - for(jj=14; z[jj-1]=='0'; jj--){} - v2 = z[0] - '0'; - for(kk=1; kkn = iRound; if( z[iRound]>='5' ){ int j = iRound-1; while( 1 /*exit-by-break*/ ){ @@ -37344,9 +36985,8 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou if( z[j]<='9' ) break; z[j] = '0'; if( j==0 ){ - z--; - z[0] = '1'; - n++; + p->z[i--] = '1'; + p->n++; p->iDP++; break; }else{ @@ -37355,13 +36995,13 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou } } } - assert( n>0 ); - while( z[n-1]=='0' ){ - n--; - assert( n>0 ); + p->z = &p->zBuf[i+1]; + assert( i+p->n < sizeof(p->zBuf) ); + assert( p->n>0 ); + while( p->z[p->n-1]=='0' ){ + p->n--; + assert( p->n>0 ); } - p->n = n; - p->z = z; } /* @@ -38600,7 +38240,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ ** Debugging logic */ -/* SQLITE_KV_TRACE() is used for tracing calls to kvrecord routines. */ +/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */ #if 0 #define SQLITE_KV_TRACE(X) printf X #else @@ -38614,6 +38254,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ #define SQLITE_KV_LOG(X) #endif + /* ** Forward declaration of objects used by this VFS implementation */ @@ -38621,11 +38262,6 @@ typedef struct KVVfsFile KVVfsFile; /* A single open file. There are only two files represented by this ** VFS - the database and the rollback journal. -** -** Maintenance reminder: if this struct changes in any way, the JSON -** rendering of its structure must be updated in -** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary -** compatibility concerns, so it does not need an iVersion member. */ struct KVVfsFile { sqlite3_file base; /* IO methods */ @@ -38675,7 +38311,7 @@ static int kvvfsCurrentTime(sqlite3_vfs*, double*); static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); static sqlite3_vfs sqlite3OsKvvfsObject = { - 2, /* iVersion */ + 1, /* iVersion */ sizeof(KVVfsFile), /* szOsFile */ 1024, /* mxPathname */ 0, /* pNext */ @@ -38751,37 +38387,23 @@ static sqlite3_io_methods kvvfs_jrnl_io_methods = { /* Forward declarations for the low-level storage engine */ -#ifndef SQLITE_WASM -/* In WASM builds these are implemented in JS. */ -static int kvrecordWrite(const char*, const char *zKey, const char *zData); -static int kvrecordDelete(const char*, const char *zKey); -static int kvrecordRead(const char*, const char *zKey, char *zBuf, int nBuf); -#endif -#ifndef KVRECORD_KEY_SZ -#define KVRECORD_KEY_SZ 32 -#endif +static int kvstorageWrite(const char*, const char *zKey, const char *zData); +static int kvstorageDelete(const char*, const char *zKey); +static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf); +#define KVSTORAGE_KEY_SZ 32 /* Expand the key name with an appropriate prefix and put the result ** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least -** KVRECORD_KEY_SZ bytes. +** KVSTORAGE_KEY_SZ bytes. */ -static void kvrecordMakeKey( +static void kvstorageMakeKey( const char *zClass, const char *zKeyIn, char *zKeyOut ){ - assert( zKeyIn ); - assert( zKeyOut ); - assert( zClass ); - sqlite3_snprintf(KVRECORD_KEY_SZ, zKeyOut, "kvvfs-%s-%s", - zClass, zKeyIn); + sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); } -#ifndef SQLITE_WASM -/* In WASM builds do not define APIs which use fopen(), fwrite(), -** and the like because those APIs are a portability issue for -** WASM. -*/ /* Write content into a key. zClass is the particular namespace of the ** underlying key/value store to use - either "local" or "session". ** @@ -38789,14 +38411,14 @@ static void kvrecordMakeKey( ** ** Return the number of errors. */ -static int kvrecordWrite( +static int kvstorageWrite( const char *zClass, const char *zKey, const char *zData ){ FILE *fd; - char zXKey[KVRECORD_KEY_SZ]; - kvrecordMakeKey(zClass, zKey, zXKey); + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); fd = fopen(zXKey, "wb"); if( fd ){ SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey, @@ -38814,9 +38436,9 @@ static int kvrecordWrite( ** namespace given by zClass. If the key does not previously exist, ** this routine is a no-op. */ -static int kvrecordDelete(const char *zClass, const char *zKey){ - char zXKey[KVRECORD_KEY_SZ]; - kvrecordMakeKey(zClass, zKey, zXKey); +static int kvstorageDelete(const char *zClass, const char *zKey){ + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); unlink(zXKey); SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey)); return 0; @@ -38837,7 +38459,7 @@ static int kvrecordDelete(const char *zClass, const char *zKey){ ** zero-terminates zBuf at zBuf[0] and returns the size of the data ** without reading it. */ -static int kvrecordRead( +static int kvstorageRead( const char *zClass, const char *zKey, char *zBuf, @@ -38845,8 +38467,8 @@ static int kvrecordRead( ){ FILE *fd; struct stat buf; - char zXKey[KVRECORD_KEY_SZ]; - kvrecordMakeKey(zClass, zKey, zXKey); + char zXKey[KVSTORAGE_KEY_SZ]; + kvstorageMakeKey(zClass, zKey, zXKey); if( access(zXKey, R_OK)!=0 || stat(zXKey, &buf)!=0 || !S_ISREG(buf.st_mode) @@ -38878,8 +38500,6 @@ static int kvrecordRead( return (int)n; } } -#endif /* #ifndef SQLITE_WASM */ - /* ** An internal level of indirection which enables us to replace the @@ -38887,27 +38507,17 @@ static int kvrecordRead( ** Maintenance reminder: if this struct changes in any way, the JSON ** rendering of its structure must be updated in ** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary -** compatibility concerns, so it does not need an iVersion member. +** compatibility concerns, so it does not need an iVersion +** member. */ typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods; struct sqlite3_kvvfs_methods { - int (*xRcrdRead)(const char*, const char *zKey, char *zBuf, int nBuf); - int (*xRcrdWrite)(const char*, const char *zKey, const char *zData); - int (*xRcrdDelete)(const char*, const char *zKey); + int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf); + int (*xWrite)(const char *zClass, const char *zKey, const char *zData); + int (*xDelete)(const char *zClass, const char *zKey); const int nKeySize; - const int nBufferSize; -#ifndef SQLITE_WASM -# define MAYBE_CONST const -#else -# define MAYBE_CONST -#endif - MAYBE_CONST sqlite3_vfs * pVfs; - MAYBE_CONST sqlite3_io_methods *pIoDb; - MAYBE_CONST sqlite3_io_methods *pIoJrnl; -#undef MAYBE_CONST }; - /* ** This object holds the kvvfs I/O methods which may be swapped out ** for JavaScript-side implementations in WASM builds. In such builds @@ -38922,20 +38532,10 @@ struct sqlite3_kvvfs_methods { const #endif SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { -#ifndef SQLITE_WASM - .xRcrdRead = kvrecordRead, - .xRcrdWrite = kvrecordWrite, - .xRcrdDelete = kvrecordDelete, -#else - .xRcrdRead = 0, - .xRcrdWrite = 0, - .xRcrdDelete = 0, -#endif - .nKeySize = KVRECORD_KEY_SZ, - .nBufferSize = SQLITE_KVOS_SZ, - .pVfs = &sqlite3OsKvvfsObject, - .pIoDb = &kvvfs_db_io_methods, - .pIoJrnl = &kvvfs_jrnl_io_methods +kvstorageRead, +kvstorageWrite, +kvstorageDelete, +KVSTORAGE_KEY_SZ }; /****** Utility subroutines ************************************************/ @@ -38962,10 +38562,7 @@ SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = { ** of hexadecimal and base-26 numbers, it is always clear where ** one stops and the next begins. */ -#ifndef SQLITE_WASM -static -#endif -int kvvfsEncode(const char *aData, int nData, char *aOut){ +static int kvvfsEncode(const char *aData, int nData, char *aOut){ int i, j; const unsigned char *a = (const unsigned char*)aData; for(i=j=0; izClass, "sz", zData, - sizeof(zData)-1); + sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1); return strtoll(zData, 0, 0); } static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){ char zData[50]; sqlite3_snprintf(sizeof(zData), zData, "%lld", sz); - return sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "sz", zData); + return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData); } /****** sqlite3_io_methods methods ******************************************/ @@ -39122,9 +38714,6 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ pFile->isJournal ? "journal" : "db")); sqlite3_free(pFile->aJrnl); sqlite3_free(pFile->aData); -#ifdef SQLITE_WASM - memset(pFile, 0, sizeof(*pFile)); -#endif return SQLITE_OK; } @@ -39141,22 +38730,16 @@ static int kvvfsReadJrnl( assert( pFile->isJournal ); SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); if( pFile->aJrnl==0 ){ - int rc; - int szTxt = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl", - 0, 0); + int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0); char *aTxt; if( szTxt<=4 ){ return SQLITE_IOERR; } aTxt = sqlite3_malloc64( szTxt+1 ); if( aTxt==0 ) return SQLITE_NOMEM; - rc = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, "jrnl", - aTxt, szTxt+1); - if( rc>=0 ){ - kvvfsDecodeJournal(pFile, aTxt, szTxt); - } + kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1); + kvvfsDecodeJournal(pFile, aTxt, szTxt); sqlite3_free(aTxt); - if( rc ) return rc; if( pFile->aJrnl==0 ) return SQLITE_IOERR; } if( iOfst+iAmt>pFile->nJrnl ){ @@ -39196,8 +38779,8 @@ static int kvvfsReadDb( pgno = 1; } sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - got = sqlite3KvvfsMethods.xRcrdRead(pFile->zClass, zKey, - aData, SQLITE_KVOS_SZ-1); + got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey, + aData, SQLITE_KVOS_SZ-1); if( got<0 ){ n = 0; }else{ @@ -39265,7 +38848,6 @@ static int kvvfsWriteDb( unsigned int pgno; char zKey[30]; char *aData = pFile->aData; - int rc; SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst)); assert( iAmt>=512 && iAmt<=65536 ); assert( (iAmt & (iAmt-1))==0 ); @@ -39274,13 +38856,13 @@ static int kvvfsWriteDb( pgno = 1 + iOfst/iAmt; sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); kvvfsEncode(zBuf, iAmt, aData); - rc = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, zKey, aData); - if( 0==rc ){ - if( iOfst+iAmt > pFile->szDb ){ - pFile->szDb = iOfst + iAmt; - } + if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){ + return SQLITE_IOERR; } - return rc; + if( iOfst+iAmt > pFile->szDb ){ + pFile->szDb = iOfst + iAmt; + } + return SQLITE_OK; } /* @@ -39290,7 +38872,7 @@ static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){ KVVfsFile *pFile = (KVVfsFile *)pProtoFile; SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size)); assert( size==0 ); - sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, "jrnl"); + sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl"); sqlite3_free(pFile->aJrnl); pFile->aJrnl = 0; pFile->nJrnl = 0; @@ -39309,7 +38891,7 @@ static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){ pgnoMax = 2 + pFile->szDb/pFile->szPage; while( pgno<=pgnoMax ){ sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno); - sqlite3KvvfsMethods.xRcrdDelete(pFile->zClass, zKey); + sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey); pgno++; } pFile->szDb = size; @@ -39341,7 +38923,7 @@ static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){ }while( n>0 ); zOut[i++] = ' '; kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]); - i = sqlite3KvvfsMethods.xRcrdWrite(pFile->zClass, "jrnl", zOut); + i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut); sqlite3_free(zOut); return i ? SQLITE_IOERR : SQLITE_OK; } @@ -39455,32 +39037,33 @@ static int kvvfsOpen( KVVfsFile *pFile = (KVVfsFile*)pProtoFile; if( zName==0 ) zName = ""; SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName)); - assert(!pFile->zClass); - assert(!pFile->aData); - assert(!pFile->aJrnl); - assert(!pFile->nJrnl); - assert(!pFile->base.pMethods); - pFile->szPage = -1; - pFile->szDb = -1; - if( 0==sqlite3_strglob("*-journal", zName) ){ + if( strcmp(zName, "local")==0 + || strcmp(zName, "session")==0 + ){ + pFile->isJournal = 0; + pFile->base.pMethods = &kvvfs_db_io_methods; + }else + if( strcmp(zName, "local-journal")==0 + || strcmp(zName, "session-journal")==0 + ){ pFile->isJournal = 1; pFile->base.pMethods = &kvvfs_jrnl_io_methods; - if( 0==strcmp("session-journal",zName) ){ - pFile->zClass = "session"; - }else if( 0==strcmp("local-journal",zName) ){ - pFile->zClass = "local"; - } }else{ - pFile->isJournal = 0; - pFile->base.pMethods = &kvvfs_db_io_methods; + return SQLITE_CANTOPEN; } - if( !pFile->zClass ){ - pFile->zClass = zName; + if( zName[0]=='s' ){ + pFile->zClass = "session"; + }else{ + pFile->zClass = "local"; } pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ); if( pFile->aData==0 ){ return SQLITE_NOMEM; } + pFile->aJrnl = 0; + pFile->nJrnl = 0; + pFile->szPage = -1; + pFile->szDb = -1; return SQLITE_OK; } @@ -39490,17 +39073,13 @@ static int kvvfsOpen( ** returning. */ static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - int rc /* The JS impl can fail with OOM in argument conversion */; if( strcmp(zPath, "local-journal")==0 ){ - rc = sqlite3KvvfsMethods.xRcrdDelete("local", "jrnl"); + sqlite3KvvfsMethods.xDelete("local", "jrnl"); }else if( strcmp(zPath, "session-journal")==0 ){ - rc = sqlite3KvvfsMethods.xRcrdDelete("session", "jrnl"); + sqlite3KvvfsMethods.xDelete("session", "jrnl"); } - else{ - rc = 0; - } - return rc; + return SQLITE_OK; } /* @@ -39514,42 +39093,21 @@ static int kvvfsAccess( int *pResOut ){ SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath)); -#if 0 && defined(SQLITE_WASM) - /* - ** This is not having the desired effect in the JS bindings. - ** It's ostensibly the same logic as the #else block, but - ** it's not behaving that way. - ** - ** In JS we map all zPaths to Storage objects, and -journal files - ** are mapped to the storage for the main db (which is is exactly - ** what the mapping of "local-journal" -> "local" is doing). - */ - const char *zKey = (0==sqlite3_strglob("*-journal", zPath)) - ? "jrnl" : "sz"; - *pResOut = - sqlite3KvvfsMethods.xRcrdRead(zPath, zKey, 0, 0)>0; -#else if( strcmp(zPath, "local-journal")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("local", "jrnl", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0; }else if( strcmp(zPath, "session-journal")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("session", "jrnl", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0; }else if( strcmp(zPath, "local")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("local", "sz", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0; }else if( strcmp(zPath, "session")==0 ){ - *pResOut = - sqlite3KvvfsMethods.xRcrdRead("session", "sz", 0, 0)>0; + *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0; }else { *pResOut = 0; } - /*all current JS tests avoid triggering: assert( *pResOut == 0 ); */ -#endif SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut)); return SQLITE_OK; } @@ -44833,7 +44391,7 @@ static int unixShmMap( } /* Map the requested memory region into this processes address space. */ - apNew = (char **)sqlite3_realloc64( + apNew = (char **)sqlite3_realloc( pShmNode->apRegion, nReqRegion*sizeof(char *) ); if( !apNew ){ @@ -48278,7 +47836,7 @@ SQLITE_API int sqlite3_os_end(void){ ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions ** based on the sub-platform)? */ -#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_ANSI) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI) # define SQLITE_WIN32_HAS_ANSI #endif @@ -48286,7 +47844,7 @@ SQLITE_API int sqlite3_os_end(void){ ** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions ** based on the sub-platform)? */ -#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT) && \ +#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \ !defined(SQLITE_WIN32_NO_WIDE) # define SQLITE_WIN32_HAS_WIDE #endif @@ -48425,7 +47983,16 @@ SQLITE_API int sqlite3_os_end(void){ */ #if SQLITE_WIN32_FILEMAPPING_API && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +/* +** Two of the file mapping APIs are different under WinRT. Figure out which +** set we need. +*/ +#if SQLITE_OS_WINRT +WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \ + LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR); +WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T); +#else #if defined(SQLITE_WIN32_HAS_ANSI) WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \ DWORD, DWORD, DWORD, LPCSTR); @@ -48437,6 +48004,7 @@ WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \ #endif /* defined(SQLITE_WIN32_HAS_WIDE) */ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); +#endif /* SQLITE_OS_WINRT */ /* ** These file mapping APIs are common to both Win32 and WinRT. @@ -48727,7 +48295,7 @@ static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; ** This function is not available on Windows CE or WinRT. */ -#if SQLITE_OS_WINCE +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define osAreFileApisANSI() 1 #endif @@ -48742,7 +48310,7 @@ static struct win_syscall { sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ sqlite3_syscall_ptr pDefault; /* Default value */ } aSyscall[] = { -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, #else { "AreFileApisANSI", (SYSCALL)0, 0 }, @@ -48781,7 +48349,7 @@ static struct win_syscall { #define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateFileW", (SYSCALL)CreateFileW, 0 }, #else { "CreateFileW", (SYSCALL)0, 0 }, @@ -48790,7 +48358,7 @@ static struct win_syscall { #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) -#if defined(SQLITE_WIN32_HAS_ANSI) && \ +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \ SQLITE_WIN32_CREATEFILEMAPPINGA { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, @@ -48801,8 +48369,8 @@ static struct win_syscall { #define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) -#if (SQLITE_OS_WINCE || defined(SQLITE_WIN32_HAS_WIDE)) && \ - (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, @@ -48811,7 +48379,7 @@ static struct win_syscall { #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, #else { "CreateMutexW", (SYSCALL)0, 0 }, @@ -48897,7 +48465,7 @@ static struct win_syscall { #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ LPDWORD))aSyscall[18].pCurrent) -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, #else { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, @@ -48914,7 +48482,7 @@ static struct win_syscall { #define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, #else { "GetFileAttributesW", (SYSCALL)0, 0 }, @@ -48931,7 +48499,11 @@ static struct win_syscall { #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ LPVOID))aSyscall[22].pCurrent) +#if !SQLITE_OS_WINRT { "GetFileSize", (SYSCALL)GetFileSize, 0 }, +#else + { "GetFileSize", (SYSCALL)0, 0 }, +#endif #define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) @@ -48944,7 +48516,7 @@ static struct win_syscall { #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ LPSTR*))aSyscall[24].pCurrent) -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, #else { "GetFullPathNameW", (SYSCALL)0, 0 }, @@ -48979,10 +48551,16 @@ static struct win_syscall { #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ LPCSTR))aSyscall[27].pCurrent) +#if !SQLITE_OS_WINRT { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, +#else + { "GetSystemInfo", (SYSCALL)0, 0 }, +#endif + #define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, + #define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) #if !SQLITE_OS_WINCE @@ -49002,7 +48580,7 @@ static struct win_syscall { #define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, #else { "GetTempPathW", (SYSCALL)0, 0 }, @@ -49010,7 +48588,11 @@ static struct win_syscall { #define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) +#if !SQLITE_OS_WINRT { "GetTickCount", (SYSCALL)GetTickCount, 0 }, +#else + { "GetTickCount", (SYSCALL)0, 0 }, +#endif #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) @@ -49023,7 +48605,7 @@ static struct win_syscall { #define osGetVersionExA ((BOOL(WINAPI*)( \ LPOSVERSIONINFOA))aSyscall[34].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) && \ +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ SQLITE_WIN32_GETVERSIONEX { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, #else @@ -49038,12 +48620,20 @@ static struct win_syscall { #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ SIZE_T))aSyscall[36].pCurrent) +#if !SQLITE_OS_WINRT { "HeapCreate", (SYSCALL)HeapCreate, 0 }, +#else + { "HeapCreate", (SYSCALL)0, 0 }, +#endif #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ SIZE_T))aSyscall[37].pCurrent) +#if !SQLITE_OS_WINRT { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, +#else + { "HeapDestroy", (SYSCALL)0, 0 }, +#endif #define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent) @@ -49061,12 +48651,16 @@ static struct win_syscall { #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ LPCVOID))aSyscall[41].pCurrent) +#if !SQLITE_OS_WINRT { "HeapValidate", (SYSCALL)HeapValidate, 0 }, +#else + { "HeapValidate", (SYSCALL)0, 0 }, +#endif #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ LPCVOID))aSyscall[42].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "HeapCompact", (SYSCALL)HeapCompact, 0 }, #else { "HeapCompact", (SYSCALL)0, 0 }, @@ -49082,7 +48676,7 @@ static struct win_syscall { #define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) && \ +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ !defined(SQLITE_OMIT_LOAD_EXTENSION) { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, #else @@ -49091,11 +48685,15 @@ static struct win_syscall { #define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent) +#if !SQLITE_OS_WINRT { "LocalFree", (SYSCALL)LocalFree, 0 }, +#else + { "LocalFree", (SYSCALL)0, 0 }, +#endif #define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "LockFile", (SYSCALL)LockFile, 0 }, #else { "LockFile", (SYSCALL)0, 0 }, @@ -49117,7 +48715,8 @@ static struct win_syscall { LPOVERLAPPED))aSyscall[48].pCurrent) #endif -#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 +#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ + (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, #else { "MapViewOfFile", (SYSCALL)0, 0 }, @@ -49145,12 +48744,20 @@ static struct win_syscall { #define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent) +#if !SQLITE_OS_WINRT { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, +#else + { "SetFilePointer", (SYSCALL)0, 0 }, +#endif #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ DWORD))aSyscall[54].pCurrent) +#if !SQLITE_OS_WINRT { "Sleep", (SYSCALL)Sleep, 0 }, +#else + { "Sleep", (SYSCALL)0, 0 }, +#endif #define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent) @@ -49159,7 +48766,7 @@ static struct win_syscall { #define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \ LPFILETIME))aSyscall[56].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "UnlockFile", (SYSCALL)UnlockFile, 0 }, #else { "UnlockFile", (SYSCALL)0, 0 }, @@ -49197,6 +48804,15 @@ static struct win_syscall { #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ LPOVERLAPPED))aSyscall[61].pCurrent) +#if SQLITE_OS_WINRT + { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, +#else + { "CreateEventExW", (SYSCALL)0, 0 }, +#endif + +#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ + DWORD,DWORD))aSyscall[62].pCurrent) + /* ** For WaitForSingleObject(), MSDN says: ** @@ -49206,7 +48822,7 @@ static struct win_syscall { { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ - DWORD))aSyscall[62].pCurrent) + DWORD))aSyscall[63].pCurrent) #if !SQLITE_OS_WINCE { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, @@ -49215,12 +48831,69 @@ static struct win_syscall { #endif #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ - BOOL))aSyscall[63].pCurrent) + BOOL))aSyscall[64].pCurrent) +#if SQLITE_OS_WINRT + { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, +#else + { "SetFilePointerEx", (SYSCALL)0, 0 }, +#endif + +#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ + PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent) + +#if SQLITE_OS_WINRT + { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, +#else + { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, +#endif + +#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ + FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) + +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, +#else + { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, +#endif + +#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ + SIZE_T))aSyscall[67].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateFile2", (SYSCALL)CreateFile2, 0 }, +#else + { "CreateFile2", (SYSCALL)0, 0 }, +#endif + +#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ + LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent) + +#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION) + { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, +#else + { "LoadPackagedLibrary", (SYSCALL)0, 0 }, +#endif + +#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ + DWORD))aSyscall[69].pCurrent) + +#if SQLITE_OS_WINRT + { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, +#else + { "GetTickCount64", (SYSCALL)0, 0 }, +#endif + +#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent) + +#if SQLITE_OS_WINRT { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, +#else + { "GetNativeSystemInfo", (SYSCALL)0, 0 }, +#endif #define osGetNativeSystemInfo ((VOID(WINAPI*)( \ - LPSYSTEM_INFO))aSyscall[64].pCurrent) + LPSYSTEM_INFO))aSyscall[71].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, @@ -49228,7 +48901,7 @@ static struct win_syscall { { "OutputDebugStringA", (SYSCALL)0, 0 }, #endif -#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[65].pCurrent) +#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, @@ -49236,11 +48909,20 @@ static struct win_syscall { { "OutputDebugStringW", (SYSCALL)0, 0 }, #endif -#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[66].pCurrent) +#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, -#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[67].pCurrent) +#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) + +#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) + { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, +#else + { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ + LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) /* ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" @@ -49255,25 +48937,25 @@ static struct win_syscall { { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ - SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[68].pCurrent) + SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) #endif /* defined(InterlockedCompareExchange) */ -#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { "UuidCreate", (SYSCALL)UuidCreate, 0 }, #else { "UuidCreate", (SYSCALL)0, 0 }, #endif -#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[69].pCurrent) +#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) -#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, #else { "UuidCreateSequential", (SYSCALL)0, 0 }, #endif #define osUuidCreateSequential \ - ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[70].pCurrent) + ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, @@ -49282,7 +48964,7 @@ static struct win_syscall { #endif #define osFlushViewOfFile \ - ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[71].pCurrent) + ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) /* ** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent() @@ -49299,7 +48981,7 @@ static struct win_syscall { #define osCreateEvent ( \ (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \ - aSyscall[72].pCurrent \ + aSyscall[80].pCurrent \ ) /* @@ -49316,7 +48998,7 @@ static struct win_syscall { { "CancelIo", (SYSCALL)0, 0 }, #endif -#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[73].pCurrent) +#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32) { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 }, @@ -49324,7 +49006,7 @@ static struct win_syscall { { "GetModuleHandleW", (SYSCALL)0, 0 }, #endif -#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[74].pCurrent) +#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent) #ifndef _WIN32 { "getenv", (SYSCALL)getenv, 0 }, @@ -49332,7 +49014,7 @@ static struct win_syscall { { "getenv", (SYSCALL)0, 0 }, #endif -#define osGetenv ((const char *(*)(const char *))aSyscall[75].pCurrent) +#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent) #ifndef _WIN32 { "getcwd", (SYSCALL)getcwd, 0 }, @@ -49340,7 +49022,7 @@ static struct win_syscall { { "getcwd", (SYSCALL)0, 0 }, #endif -#define osGetcwd ((char*(*)(char*,size_t))aSyscall[76].pCurrent) +#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent) #ifndef _WIN32 { "readlink", (SYSCALL)readlink, 0 }, @@ -49348,7 +49030,7 @@ static struct win_syscall { { "readlink", (SYSCALL)0, 0 }, #endif -#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[77].pCurrent) +#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent) #ifndef _WIN32 { "lstat", (SYSCALL)lstat, 0 }, @@ -49356,7 +49038,7 @@ static struct win_syscall { { "lstat", (SYSCALL)0, 0 }, #endif -#define osLstat ((int(*)(const char*,struct stat*))aSyscall[78].pCurrent) +#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent) #ifndef _WIN32 { "__errno", (SYSCALL)__errno, 0 }, @@ -49364,7 +49046,7 @@ static struct win_syscall { { "__errno", (SYSCALL)0, 0 }, #endif -#define osErrno (*((int*(*)(void))aSyscall[79].pCurrent)()) +#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)()) #ifndef _WIN32 { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 }, @@ -49373,7 +49055,7 @@ static struct win_syscall { #endif #define osCygwin_conv_path ((size_t(*)(unsigned int, \ - const void *, void *, size_t))aSyscall[80].pCurrent) + const void *, void *, size_t))aSyscall[88].pCurrent) }; /* End of the overrideable system calls */ @@ -49477,10 +49159,10 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){ DWORD lastErrno = osGetLastError(); if( lastErrno==NO_ERROR ){ @@ -49593,11 +49275,28 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ } #endif /* _WIN32 */ +/* +** The following routine suspends the current thread for at least ms +** milliseconds. This is equivalent to the Win32 Sleep() interface. +*/ +#if SQLITE_OS_WINRT +static HANDLE sleepObj = NULL; +#endif + SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ +#if SQLITE_OS_WINRT + if ( sleepObj==NULL ){ + sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, + SYNCHRONIZE); + } + assert( sleepObj!=NULL ); + osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); +#else osSleep(milliseconds); +#endif } -#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && \ +#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ SQLITE_THREADSAFE>0 SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ DWORD rc; @@ -49621,7 +49320,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ #if !SQLITE_WIN32_GETVERSIONEX # define osIsNT() (1) -#elif SQLITE_OS_WINCE || !defined(SQLITE_WIN32_HAS_ANSI) +#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) # define osIsNT() (1) #elif !defined(SQLITE_WIN32_HAS_WIDE) # define osIsNT() (0) @@ -49634,7 +49333,13 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){ ** based on the NT kernel. */ SQLITE_API int sqlite3_win32_is_nt(void){ -#if SQLITE_WIN32_GETVERSIONEX +#if SQLITE_OS_WINRT + /* + ** NOTE: The WinRT sub-platform is always assumed to be based on the NT + ** kernel. + */ + return 1; +#elif SQLITE_WIN32_GETVERSIONEX if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ #if defined(SQLITE_WIN32_HAS_ANSI) OSVERSIONINFOA sInfo; @@ -49676,7 +49381,7 @@ static void *winMemMalloc(int nBytes){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif assert( nBytes>=0 ); @@ -49698,7 +49403,7 @@ static void winMemFree(void *pPrior){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ @@ -49719,7 +49424,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif assert( nBytes>=0 ); @@ -49747,7 +49452,7 @@ static int winMemSize(void *p){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) ); #endif if( !p ) return 0; @@ -49777,7 +49482,7 @@ static int winMemInit(void *pAppData){ assert( pWinMemData->magic1==WINMEM_MAGIC1 ); assert( pWinMemData->magic2==WINMEM_MAGIC2 ); -#if SQLITE_WIN32_HEAP_CREATE +#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE if( !pWinMemData->hHeap ){ DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE; DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap; @@ -49810,7 +49515,7 @@ static int winMemInit(void *pAppData){ #endif assert( pWinMemData->hHeap!=0 ); assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif return SQLITE_OK; @@ -49828,7 +49533,7 @@ static void winMemShutdown(void *pAppData){ if( pWinMemData->hHeap ){ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#if defined(SQLITE_WIN32_MALLOC_VALIDATE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif if( pWinMemData->bOwned ){ @@ -50209,6 +49914,17 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ char *zOut = 0; if( osIsNT() ){ +#if SQLITE_OS_WINRT + WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1]; + dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + lastErrno, + 0, + zTempWide, + SQLITE_WIN32_MAX_ERRMSG_CHARS, + 0); +#else LPWSTR zTempWide = NULL; dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -50219,13 +49935,16 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ (LPWSTR) &zTempWide, 0, 0); +#endif if( dwLen > 0 ){ /* allocate a buffer and convert to UTF8 */ sqlite3BeginBenignMalloc(); zOut = winUnicodeToUtf8(zTempWide); sqlite3EndBenignMalloc(); +#if !SQLITE_OS_WINRT /* free the system buffer allocated by FormatMessage */ osLocalFree(zTempWide); +#endif } } #ifdef SQLITE_WIN32_HAS_ANSI @@ -50886,6 +50605,7 @@ static int winHandleUnlock(HANDLE h, int iOff, int nByte){ static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ int rc = SQLITE_OK; /* Return value */ +#if !SQLITE_OS_WINRT LONG upperBits; /* Most sig. 32 bits of new offset */ LONG lowerBits; /* Least sig. 32 bits of new offset */ DWORD dwRet; /* Value returned by SetFilePointer() */ @@ -50907,7 +50627,20 @@ static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){ rc = SQLITE_IOERR_SEEK; } } - OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset,sqlite3ErrName(rc))); +#else + /* This implementation works for WinRT. */ + LARGE_INTEGER x; /* The new offset */ + BOOL bRet; /* Value returned by SetFilePointerEx() */ + + x.QuadPart = iOffset; + bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN); + + if(!bRet){ + rc = SQLITE_IOERR_SEEK; + } +#endif + + OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc))); return rc; } @@ -51208,6 +50941,17 @@ static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){ */ static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ int rc = SQLITE_OK; + +#if SQLITE_OS_WINRT + FILE_STANDARD_INFO info; + BOOL b; + b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info)); + if( b ){ + *pnByte = info.EndOfFile.QuadPart; + }else{ + rc = SQLITE_IOERR_FSTAT; + } +#else DWORD upperBits = 0; DWORD lowerBits = 0; @@ -51217,6 +50961,8 @@ static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){ if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){ rc = SQLITE_IOERR_FSTAT; } +#endif + return rc; } @@ -51415,6 +51161,20 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ assert( pSize!=0 ); SimulateIOError(return SQLITE_IOERR_FSTAT); OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize)); + +#if SQLITE_OS_WINRT + { + FILE_STANDARD_INFO info; + if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, + &info, sizeof(info)) ){ + *pSize = info.EndOfFile.QuadPart; + }else{ + pFile->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, + "winFileSize", pFile->zPath); + } + } +#else { DWORD upperBits; DWORD lowerBits; @@ -51429,6 +51189,7 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ "winFileSize", pFile->zPath); } } +#endif OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n", pFile->h, pSize, *pSize, sqlite3ErrName(rc))); return rc; @@ -52390,6 +52151,20 @@ static int winHandleOpen( ** TODO: retry-on-ioerr. */ if( osIsNT() ){ +#if SQLITE_OS_WINRT + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; + memset(&extendedParameters, 0, sizeof(extendedParameters)); + extendedParameters.dwSize = sizeof(extendedParameters); + extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + extendedParameters.dwFileFlags = flag_overlapped; + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + h = osCreateFile2((LPCWSTR)zConverted, + (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ + OPEN_ALWAYS, /* dwCreationDisposition */ + &extendedParameters + ); +#else h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */ @@ -52398,6 +52173,7 @@ static int winHandleOpen( FILE_ATTRIBUTE_NORMAL|flag_overlapped, NULL ); +#endif }else{ /* Due to pre-processor directives earlier in this file, ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */ @@ -52865,7 +52641,9 @@ static int winShmMap( HANDLE hMap = NULL; /* file-mapping handle */ void *pMap = 0; /* Mapped memory region */ -#if defined(SQLITE_WIN32_HAS_WIDE) +#if SQLITE_OS_WINRT + hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL); +#elif defined(SQLITE_WIN32_HAS_WIDE) hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL); #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL); @@ -52877,9 +52655,15 @@ static int winShmMap( if( hMap ){ int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; +#if SQLITE_OS_WINRT + pMap = osMapViewOfFileFromApp(hMap, flags, + iOffset - iOffsetShift, szRegion + iOffsetShift + ); +#else pMap = osMapViewOfFile(hMap, flags, 0, iOffset - iOffsetShift, szRegion + iOffsetShift ); +#endif OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", osGetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion, pMap ? "ok" : "failed")); @@ -53012,7 +52796,9 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ flags |= FILE_MAP_WRITE; } #endif -#if defined(SQLITE_WIN32_HAS_WIDE) +#if SQLITE_OS_WINRT + pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); +#elif defined(SQLITE_WIN32_HAS_WIDE) pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, (DWORD)((nMap>>32) & 0xffffffff), (DWORD)(nMap & 0xffffffff), NULL); @@ -53032,7 +52818,11 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ } assert( (nMap % winSysInfo.dwPageSize)==0 ); assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); +#if SQLITE_OS_WINRT + pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap); +#else pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap); +#endif if( pNew==NULL ){ osCloseHandle(pFd->hMap); pFd->hMap = NULL; @@ -53367,6 +53157,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ } #endif +#if !SQLITE_OS_WINRT && defined(_WIN32) else if( osIsNT() ){ char *zMulti; LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) ); @@ -53420,6 +53211,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ } } #endif /* SQLITE_WIN32_HAS_ANSI */ +#endif /* !SQLITE_OS_WINRT */ /* ** Check to make sure the temporary directory ends with an appropriate @@ -53594,6 +53386,13 @@ static int winOpen( memset(pFile, 0, sizeof(winFile)); pFile->h = INVALID_HANDLE_VALUE; +#if SQLITE_OS_WINRT + if( !zUtf8Name && !sqlite3_temp_directory ){ + sqlite3_log(SQLITE_ERROR, + "sqlite3_temp_directory variable should be set for WinRT"); + } +#endif + /* If the second argument to this function is NULL, generate a ** temporary file name to use */ @@ -53676,6 +53475,31 @@ static int winOpen( #endif if( osIsNT() ){ +#if SQLITE_OS_WINRT + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; + extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + extendedParameters.dwFileAttributes = + dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; + extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParameters.lpSecurityAttributes = NULL; + extendedParameters.hTemplateFile = NULL; + do{ + h = osCreateFile2((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + &extendedParameters); + if( h!=INVALID_HANDLE_VALUE ) break; + if( isReadWrite ){ + int rc2; + sqlite3BeginBenignMalloc(); + rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ|NORETRY, &isRO); + sqlite3EndBenignMalloc(); + if( rc2==SQLITE_OK && isRO ) break; + } + }while( winRetryIoerr(&cnt, &lastErrno) ); +#else do{ h = osCreateFileW((LPCWSTR)zConverted, dwDesiredAccess, @@ -53692,6 +53516,7 @@ static int winOpen( if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); +#endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ @@ -53828,7 +53653,25 @@ static int winDelete( } if( osIsNT() ){ do { +#if SQLITE_OS_WINRT + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, + &sAttrData) ){ + attr = sAttrData.dwFileAttributes; + }else{ + lastErrno = osGetLastError(); + if( lastErrno==ERROR_FILE_NOT_FOUND + || lastErrno==ERROR_PATH_NOT_FOUND ){ + rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ + }else{ + rc = SQLITE_ERROR; + } + break; + } +#else attr = osGetFileAttributesW(zConverted); +#endif if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND @@ -53951,7 +53794,6 @@ static int winAccess( attr = sAttrData.dwFileAttributes; } }else{ - if( noRetry ) lastErrno = osGetLastError(); winLogIoerr(cnt, __LINE__); if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ sqlite3_free(zConverted); @@ -54120,7 +53962,7 @@ static int winFullPathnameNoMutex( int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */ ){ -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT int nByte; void *zConverted; char *zOut; @@ -54209,7 +54051,7 @@ static int winFullPathnameNoMutex( } #endif /* __CYGWIN__ */ -#if SQLITE_OS_WINCE && defined(_WIN32) +#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32) SimulateIOError( return SQLITE_ERROR ); /* WinCE has no concept of a relative pathname, or so I am told. */ /* WinRT has no way to convert a relative path to an absolute one. */ @@ -54228,7 +54070,7 @@ static int winFullPathnameNoMutex( return SQLITE_OK; #endif -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT #if defined(_WIN32) /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -54360,7 +54202,11 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ return 0; } if( osIsNT() ){ +#if SQLITE_OS_WINRT + h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); +#else h = osLoadLibraryW((LPCWSTR)zConverted); +#endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ @@ -54442,16 +54288,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ DWORD pid = osGetCurrentProcessId(); xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD)); } +#if SQLITE_OS_WINRT + { + ULONGLONG cnt = osGetTickCount64(); + xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG)); + } +#else { DWORD cnt = osGetTickCount(); xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD)); } +#endif /* SQLITE_OS_WINRT */ { LARGE_INTEGER i; osQueryPerformanceCounter(&i); xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER)); } -#if !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID { UUID id; memset(&id, 0, sizeof(UUID)); @@ -54461,7 +54314,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ osUuidCreateSequential(&id); xorMemory(&e, (unsigned char*)&id, sizeof(UUID)); } -#endif /* !SQLITE_OS_WINCE && SQLITE_WIN32_USE_UUID */ +#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */ return e.nXor>nBuf ? nBuf : e.nXor; #endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */ } @@ -54692,16 +54545,15 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==81 ); - assert( strcmp(aSyscall[0].zName,"AreFileApisANSI")==0 ); - assert( strcmp(aSyscall[20].zName,"GetFileAttributesA")==0 ); - assert( strcmp(aSyscall[40].zName,"HeapReAlloc")==0 ); - assert( strcmp(aSyscall[60].zName,"WideCharToMultiByte")==0 ); - assert( strcmp(aSyscall[80].zName,"cygwin_conv_path")==0 ); + assert( ArraySize(aSyscall)==89 ); /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); +#if SQLITE_OS_WINRT + osGetNativeSystemInfo(&winSysInfo); +#else osGetSystemInfo(&winSysInfo); +#endif assert( winSysInfo.dwAllocationGranularity>0 ); assert( winSysInfo.dwPageSize>0 ); @@ -54725,9 +54577,17 @@ SQLITE_API int sqlite3_os_init(void){ } SQLITE_API int sqlite3_os_end(void){ +#if SQLITE_OS_WINRT + if( sleepObj!=NULL ){ + osCloseHandle(sleepObj); + sleepObj = NULL; + } +#endif + #ifndef SQLITE_OMIT_WAL winBigLock = 0; #endif + return SQLITE_OK; } @@ -59876,8 +59736,6 @@ SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ (void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); if( iRead ) return 0; /* Case (4) */ } -#else - UNUSED_PARAMETER(pgno); #endif assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 ); if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd) @@ -60298,17 +60156,17 @@ static int jrnlBufferSize(Pager *pPager){ */ #ifdef SQLITE_CHECK_PAGES /* -** Return a 64-bit hash of the page data for pPage. +** Return a 32-bit hash of the page data for pPage. */ -static u64 pager_datahash(int nByte, unsigned char *pData){ - u64 hash = 0; +static u32 pager_datahash(int nByte, unsigned char *pData){ + u32 hash = 0; int i; for(i=0; ipPager->pageSize, (unsigned char *)pPage->pData); } static void pager_set_pagehash(PgHdr *pPage){ @@ -63257,8 +63115,6 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); pPager->pWal = 0; } -#else - UNUSED_PARAMETER(db); #endif pager_reset(pPager); if( MEMDB ){ @@ -76268,30 +76124,6 @@ static SQLITE_NOINLINE int btreeBeginTrans( } #endif -#ifdef SQLITE_EXPERIMENTAL_PRAGMA_20251114 - /* If both a read and write transaction will be opened by this call, - ** then issue a file-control as if the following pragma command had - ** been evaluated: - ** - ** PRAGMA experimental_pragma_20251114 = 1|2 - ** - ** where the RHS is "1" if wrflag is 1 (RESERVED lock), or "2" if wrflag - ** is 2 (EXCLUSIVE lock). Ignore any result or error returned by the VFS. - ** - ** WARNING: This code will likely remain part of SQLite only temporarily - - ** it exists to allow users to experiment with certain types of blocking - ** locks in custom VFS implementations. It MAY BE REMOVED AT ANY TIME. */ - if( pBt->pPage1==0 && wrflag ){ - sqlite3_file *fd = sqlite3PagerFile(pPager); - char *aFcntl[3] = {0,0,0}; - aFcntl[1] = "experimental_pragma_20251114"; - assert( wrflag==1 || wrflag==2 ); - aFcntl[2] = (wrflag==1 ? "1" : "2"); - sqlite3OsFileControlHint(fd, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); - sqlite3_free(aFcntl[0]); - } -#endif - /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after @@ -78296,7 +78128,7 @@ SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){ assert( cursorOwnsBtShared(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - if( NEVER(pCur->eState==CURSOR_VALID) ){ + if( pCur->eState==CURSOR_VALID ){ *pRes = 0; return SQLITE_OK; } @@ -82377,7 +82209,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 }while( rc==SQLITE_OK && nOut>0 ); if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){ - Pgno pgnoNew = 0; /* Prevent harmless static-analyzer warning */ + Pgno pgnoNew; MemPage *pNew = 0; rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); put4byte(pPgnoOut, pgnoNew); @@ -85043,27 +84875,21 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){ StrAccum acc; assert( p->flags & (MEM_Int|MEM_Real|MEM_IntReal) ); assert( sz>22 ); - if( p->flags & (MEM_Int|MEM_IntReal) ){ -#if GCC_VERSION>=7000000 && GCC_VERSION<15000000 && defined(__i386__) - /* Work-around for GCC bug or bugs: - ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 - ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659 - ** The problem appears to be fixed in GCC 15 */ + if( p->flags & MEM_Int ){ +#if GCC_VERSION>=7000000 + /* Work-around for GCC bug + ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 */ i64 x; - assert( (MEM_Str&~p->flags)*4==sizeof(x) ); - memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4); + assert( (p->flags&MEM_Int)*2==sizeof(x) ); + memcpy(&x, (char*)&p->u, (p->flags&MEM_Int)*2); p->n = sqlite3Int64ToText(x, zBuf); #else p->n = sqlite3Int64ToText(p->u.i, zBuf); #endif - if( p->flags & MEM_IntReal ){ - memcpy(zBuf+p->n,".0", 3); - p->n += 2; - } }else{ sqlite3StrAccumInit(&acc, 0, zBuf, sz, 0); - sqlite3_str_appendf(&acc, "%!.*g", - (p->db ? p->db->nFpDigit : 17), p->u.r); + sqlite3_str_appendf(&acc, "%!.15g", + (p->flags & MEM_IntReal)!=0 ? (double)p->u.i : p->u.r); assert( acc.zText==zBuf && acc.mxAlloc<=0 ); zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */ p->n = acc.nChar; @@ -85112,9 +84938,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemValidStrRep(Mem *p){ assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 ); } if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1; - if( p->db==0 ){ - return 1; /* db->nFpDigit required to validate p->z[] */ - } memcpy(&tmp, p, sizeof(tmp)); vdbeMemRenderNum(sizeof(zBuf), zBuf, &tmp); z = p->z; @@ -85265,16 +85088,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){ ** ** This is an optimization. Correct operation continues even if ** this routine is a no-op. -** -** Return true if the strig is zero-terminated after this routine is -** called and false if it is not. */ -SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ +SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ if( (pMem->flags & (MEM_Str|MEM_Term|MEM_Ephem|MEM_Static))!=MEM_Str ){ /* pMem must be a string, and it cannot be an ephemeral or static string */ - return 0; + return; } - if( pMem->enc!=SQLITE_UTF8 ) return 0; + if( pMem->enc!=SQLITE_UTF8 ) return; assert( pMem->z!=0 ); if( pMem->flags & MEM_Dyn ){ if( pMem->xDel==sqlite3_free @@ -85282,19 +85102,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){ ){ pMem->z[pMem->n] = 0; pMem->flags |= MEM_Term; - return 1; + return; } if( pMem->xDel==sqlite3RCStrUnref ){ /* Blindly assume that all RCStr objects are zero-terminated */ pMem->flags |= MEM_Term; - return 1; + return; } }else if( pMem->szMalloc >= pMem->n+1 ){ pMem->z[pMem->n] = 0; pMem->flags |= MEM_Term; - return 1; + return; } - return 0; } /* @@ -85592,70 +85411,18 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ } } -/* -** Invoke sqlite3AtoF() on the text value of pMem and return the -** double result. If sqlite3AtoF() returns an error code, write -** that code into *pRC if (*pRC)!=NULL. -** -** The caller must ensure that pMem->db!=0 and that pMem is in -** mode MEM_Str or MEM_Blob. -*/ -SQLITE_PRIVATE SQLITE_NOINLINE double sqlite3MemRealValueRC(Mem *pMem, int *pRC){ - double val = (double)0; - int rc = 0; - assert( pMem->db!=0 ); - assert( pMem->flags & (MEM_Str|MEM_Blob) ); - if( pMem->z==0 ){ - /* no-op */ - }else if( pMem->enc==SQLITE_UTF8 - && ((pMem->flags & MEM_Term)!=0 || sqlite3VdbeMemZeroTerminateIfAble(pMem)) - ){ - rc = sqlite3AtoF(pMem->z, &val); - }else if( pMem->n==0 ){ - /* no-op */ - }else if( pMem->enc==SQLITE_UTF8 ){ - char *zCopy = sqlite3DbStrNDup(pMem->db, pMem->z, pMem->n); - if( zCopy ){ - rc = sqlite3AtoF(zCopy, &val); - sqlite3DbFree(pMem->db, zCopy); - } - }else{ - int n, i, j; - char *zCopy; - const char *z; - - n = pMem->n & ~1; - zCopy = sqlite3DbMallocRaw(pMem->db, n/2 + 2); - if( zCopy ){ - z = pMem->z; - if( pMem->enc==SQLITE_UTF16LE ){ - for(i=j=0; idb, zCopy); - } - } - if( pRC ) *pRC = rc; - return val; -} - /* ** Return the best representation of pMem that we can get into a ** double. If pMem is already a double or an integer, return its ** value. If it is a string or blob, try to convert it to a double. ** If it is a NULL, return 0.0. */ +static SQLITE_NOINLINE double memRealValue(Mem *pMem){ + /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ + double val = (double)0; + sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc); + return val; +} SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); @@ -85666,7 +85433,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ testcase( pMem->flags & MEM_IntReal ); return (double)pMem->u.i; }else if( pMem->flags & (MEM_Str|MEM_Blob) ){ - return sqlite3MemRealValueRC(pMem, 0); + return memRealValue(pMem); }else{ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ return (double)0; @@ -85790,7 +85557,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ sqlite3_int64 ix; assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); - pMem->u.r = sqlite3MemRealValueRC(pMem, &rc); + rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1) || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r))) ){ @@ -86255,84 +86022,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( return SQLITE_OK; } -/* Like sqlite3VdbeMemSetStr() except: -** -** enc is always SQLITE_UTF8 -** pMem->db is always non-NULL -*/ -SQLITE_PRIVATE int sqlite3VdbeMemSetText( - Mem *pMem, /* Memory cell to set to string value */ - const char *z, /* String pointer */ - i64 n, /* Bytes in string, or negative */ - void (*xDel)(void*) /* Destructor function */ -){ - i64 nByte = n; /* New value for pMem->n */ - u16 flags; - - assert( pMem!=0 ); - assert( pMem->db!=0 ); - assert( sqlite3_mutex_held(pMem->db->mutex) ); - assert( !sqlite3VdbeMemIsRowSet(pMem) ); - - /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ - if( !z ){ - sqlite3VdbeMemSetNull(pMem); - return SQLITE_OK; - } - - if( nByte<0 ){ - nByte = strlen(z); - flags = MEM_Str|MEM_Term; - }else{ - flags = MEM_Str; - } - if( nByte>(i64)pMem->db->aLimit[SQLITE_LIMIT_LENGTH] ){ - if( xDel && xDel!=SQLITE_TRANSIENT ){ - if( xDel==SQLITE_DYNAMIC ){ - sqlite3DbFree(pMem->db, (void*)z); - }else{ - xDel((void*)z); - } - } - sqlite3VdbeMemSetNull(pMem); - return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); - } - - /* The following block sets the new values of Mem.z and Mem.xDel. It - ** also sets a flag in local variable "flags" to indicate the memory - ** management (one of MEM_Dyn or MEM_Static). - */ - if( xDel==SQLITE_TRANSIENT ){ - i64 nAlloc = nByte + 1; - testcase( nAlloc==31 ); - testcase( nAlloc==32 ); - if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ - return SQLITE_NOMEM_BKPT; - } - assert( pMem->z!=0 ); - memcpy(pMem->z, z, nByte); - pMem->z[nByte] = 0; - }else{ - sqlite3VdbeMemRelease(pMem); - pMem->z = (char *)z; - if( xDel==SQLITE_DYNAMIC ){ - pMem->zMalloc = pMem->z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); - pMem->xDel = 0; - }else if( xDel==SQLITE_STATIC ){ - pMem->xDel = xDel; - flags |= MEM_Static; - }else{ - pMem->xDel = xDel; - flags |= MEM_Dyn; - } - } - pMem->flags = flags; - pMem->n = (int)(nByte & 0x7fffffff); - pMem->enc = SQLITE_UTF8; - return SQLITE_OK; -} - /* ** Move data out of a btree key or data field and into a Mem structure. ** The data is payload from the entry that pCur is currently pointing @@ -86761,7 +86450,7 @@ static int valueFromExpr( if( affinity==SQLITE_AFF_BLOB ){ if( op==TK_FLOAT ){ assert( pVal && pVal->z && pVal->flags==(MEM_Str|MEM_Term) ); - sqlite3AtoF(pVal->z, &pVal->u.r); + sqlite3AtoF(pVal->z, &pVal->u.r, pVal->n, SQLITE_UTF8); pVal->flags = MEM_Real; }else if( op==TK_INTEGER ){ /* This case is required by -9223372036854775808 and other strings @@ -87029,11 +86718,6 @@ SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr( ** ** If *ppVal is initially NULL then the caller is responsible for ** ensuring that the value written into *ppVal is eventually freed. -** -** If the buffer does not contain a well-formed record, this routine may -** read several bytes past the end of the buffer. Callers must therefore -** ensure that any buffer which may contain a corrupt record is padded -** with at least 8 bytes of addressable memory. */ SQLITE_PRIVATE int sqlite3Stat4Column( sqlite3 *db, /* Database handle */ @@ -90050,7 +89734,7 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName( } assert( p->aColName!=0 ); pColName = &(p->aColName[idx+var*p->nResAlloc]); - rc = sqlite3VdbeMemSetText(pColName, zName, -1, xDel); + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); return rc; } @@ -93128,23 +92812,7 @@ static void setResultStrOrError( void (*xDel)(void*) /* Destructor function */ ){ Mem *pOut = pCtx->pOut; - int rc; - if( enc==SQLITE_UTF8 ){ - rc = sqlite3VdbeMemSetText(pOut, z, n, xDel); - }else if( enc==SQLITE_UTF8_ZT ){ - /* It is usually considered improper to assert() on an input. However, - ** the following assert() is checking for inputs that are documented - ** to result in undefined behavior. */ - assert( z==0 - || n<0 - || n>pOut->db->aLimit[SQLITE_LIMIT_LENGTH] - || z[n]==0 - ); - rc = sqlite3VdbeMemSetText(pOut, z, n, xDel); - pOut->flags |= MEM_Term; - }else{ - rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); - } + int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); if( rc ){ if( rc==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(pCtx); @@ -93337,7 +93005,7 @@ SQLITE_API void sqlite3_result_text64( #endif assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){ + if( enc!=SQLITE_UTF8 ){ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; n &= ~(u64)1; } @@ -93488,8 +93156,6 @@ static int doWalCallbacks(sqlite3 *db){ } } } -#else - UNUSED_PARAMETER(db); #endif return rc; } @@ -94446,25 +94112,13 @@ static int bindText( assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */ if( zData!=0 ){ pVar = &p->aVar[i-1]; - if( encoding==SQLITE_UTF8 ){ - rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel); - }else if( encoding==SQLITE_UTF8_ZT ){ - /* It is usually consider improper to assert() on an input. - ** However, the following assert() is checking for inputs - ** that are documented to result in undefined behavior. */ - assert( zData==0 - || nData<0 - || nData>pVar->db->aLimit[SQLITE_LIMIT_LENGTH] - || ((u8*)zData)[nData]==0 - ); - rc = sqlite3VdbeMemSetText(pVar, zData, nData, xDel); - pVar->flags |= MEM_Term; - }else{ - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( encoding==0 ) pVar->enc = ENC(p->db); - } - if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); + if( rc==SQLITE_OK ){ + if( encoding==0 ){ + pVar->enc = ENC(p->db); + }else{ + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + } } if( rc ){ sqlite3Error(p->db, rc); @@ -94576,7 +94230,7 @@ SQLITE_API int sqlite3_bind_text64( unsigned char enc ){ assert( xDel!=SQLITE_DYNAMIC ); - if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF8_ZT ){ + if( enc!=SQLITE_UTF8 ){ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; nData &= ~(u64)1; } @@ -95613,26 +95267,35 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( #ifndef SQLITE_HWTIME_H #define SQLITE_HWTIME_H -#if defined(_MSC_VER) && defined(_WIN32) - -/* #include "windows.h" */ - #include - - __inline sqlite3_uint64 sqlite3Hwtime(void){ - LARGE_INTEGER tm; - QueryPerformanceCounter(&tm); - return (sqlite3_uint64)tm.QuadPart; - } - -#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \ +/* +** The following routine only works on Pentium-class (or newer) processors. +** It uses the RDTSC opcode to read the cycle count value out of the +** processor and returns that value. This can be used for high-res +** profiling. +*/ +#if !defined(__STRICT_ANSI__) && \ + (defined(__GNUC__) || defined(_MSC_VER)) && \ (defined(i386) || defined(__i386__) || defined(_M_IX86)) + #if defined(__GNUC__) + __inline__ sqlite_uint64 sqlite3Hwtime(void){ unsigned int lo, hi; __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); return (sqlite_uint64)hi << 32 | lo; } + #elif defined(_MSC_VER) + + __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){ + __asm { + rdtsc + ret ; return value at EDX:EAX + } + } + + #endif + #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__)) __inline__ sqlite_uint64 sqlite3Hwtime(void){ @@ -95641,14 +95304,6 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( return (sqlite_uint64)hi << 32 | lo; } -#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__aarch64__) - - __inline__ sqlite_uint64 sqlite3Hwtime(void){ - sqlite3_uint64 cnt; - __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r" (cnt)); - return cnt; - } - #elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__)) __inline__ sqlite_uint64 sqlite3Hwtime(void){ @@ -96007,9 +95662,10 @@ static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){ */ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ double rValue; + u8 enc = pRec->enc; int rc; assert( (pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_IntReal))==MEM_Str ); - rValue = sqlite3MemRealValueRC(pRec, &rc); + rc = sqlite3AtoF(pRec->z, &rValue, pRec->n, enc); if( rc<=0 ) return; if( rc==1 && alsoAnInt(pRec, rValue, &pRec->u.i) ){ pRec->flags |= MEM_Int; @@ -96091,10 +95747,7 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){ int eType = sqlite3_value_type(pVal); if( eType==SQLITE_TEXT ){ Mem *pMem = (Mem*)pVal; - assert( pMem->db!=0 ); - sqlite3_mutex_enter(pMem->db->mutex); applyNumericAffinity(pMem, 0); - sqlite3_mutex_leave(pMem->db->mutex); eType = sqlite3_value_type(pVal); } return eType; @@ -96127,7 +95780,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){ pMem->u.i = 0; return MEM_Int; } - pMem->u.r = sqlite3MemRealValueRC(pMem, &rc); + rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); if( rc<=0 ){ if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){ pMem->u.i = ix; @@ -102276,15 +101929,20 @@ case OP_SorterInsert: { /* in2 */ break; } -/* Opcode: IdxDelete P1 P2 P3 * * +/* Opcode: IdxDelete P1 P2 P3 * P5 ** Synopsis: key=r[P2@P3] ** ** The content of P3 registers starting at register P2 form ** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. ** -** Raise an SQLITE_CORRUPT_INDEX error if no matching index entry is found -** and not in writable_schema mode. +** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error +** if no matching index entry is found. This happens when running +** an UPDATE or DELETE statement and the index entry to be updated +** or deleted is not found. For some uses of IdxDelete +** (example: the EXCEPT operator) it does not matter that no matching +** entry is found. For those cases, P5 is zero. Also, do not raise +** this (self-correcting and non-critical) error if in writable_schema mode. */ case OP_IdxDelete: { VdbeCursor *pC; @@ -102310,7 +101968,7 @@ case OP_IdxDelete: { if( res==0 ){ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; - }else if( !sqlite3WritableSchema(db) ){ + }else if( pOp->p5 && !sqlite3WritableSchema(db) ){ rc = sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption"); goto abort_due_to_error; } @@ -110404,7 +110062,7 @@ static int exprProbability(Expr *p){ double r = -1.0; if( p->op!=TK_FLOAT ) return -1; assert( !ExprHasProperty(p, EP_IntValue) ); - sqlite3AtoF(p->u.zToken, &r); + sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8); assert( r>=0.0 ); if( r>1.0 ) return -1; return (int)(r*134217728.0); @@ -111124,8 +110782,10 @@ static int resolveCompoundOrderBy( /* Convert the ORDER BY term into an integer column number iCol, ** taking care to preserve the COLLATE clause if it exists. */ if( !IN_RENAME_OBJECT ){ - Expr *pNew = sqlite3ExprInt32(db, iCol); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return 1; + pNew->flags |= EP_IntValue; + pNew->u.iValue = iCol; if( pItem->pExpr==pE ){ pItem->pExpr = pNew; }else{ @@ -111479,6 +111139,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } #endif + /* The ORDER BY and GROUP BY clauses may not refer to terms in + ** outer queries + */ + sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg|NC_AllowWin; /* If this is a converted compound query, move the ORDER BY clause from @@ -112725,22 +112389,34 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc( int dequote /* True to dequote */ ){ Expr *pNew; - int nExtra = pToken ? pToken->n+1 : 0; + int nExtra = 0; + int iValue = 0; assert( db!=0 ); + if( pToken ){ + if( op!=TK_INTEGER || pToken->z==0 + || sqlite3GetInt32(pToken->z, &iValue)==0 ){ + nExtra = pToken->n+1; /* tag-20240227-a */ + assert( iValue>=0 ); + } + } pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)+nExtra); if( pNew ){ memset(pNew, 0, sizeof(Expr)); pNew->op = (u8)op; pNew->iAgg = -1; - if( nExtra ){ - assert( pToken!=0 ); - pNew->u.zToken = (char*)&pNew[1]; - assert( pToken->z!=0 || pToken->n==0 ); - if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); - pNew->u.zToken[pToken->n] = 0; - if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ - sqlite3DequoteExpr(pNew); + if( pToken ){ + if( nExtra==0 ){ + pNew->flags |= EP_IntValue|EP_Leaf|(iValue?EP_IsTrue:EP_IsFalse); + pNew->u.iValue = iValue; + }else{ + pNew->u.zToken = (char*)&pNew[1]; + assert( pToken->z!=0 || pToken->n==0 ); + if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n); + pNew->u.zToken[pToken->n] = 0; + if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){ + sqlite3DequoteExpr(pNew); + } } } #if SQLITE_MAX_EXPR_DEPTH>0 @@ -112765,24 +112441,6 @@ SQLITE_PRIVATE Expr *sqlite3Expr( return sqlite3ExprAlloc(db, op, &x, 0); } -/* -** Allocate an expression for a 32-bit signed integer literal. -*/ -SQLITE_PRIVATE Expr *sqlite3ExprInt32(sqlite3 *db, int iVal){ - Expr *pNew = sqlite3DbMallocRawNN(db, sizeof(Expr)); - if( pNew ){ - memset(pNew, 0, sizeof(Expr)); - pNew->op = TK_INTEGER; - pNew->iAgg = -1; - pNew->flags = EP_IntValue|EP_Leaf|(iVal?EP_IsTrue:EP_IsFalse); - pNew->u.iValue = iVal; -#if SQLITE_MAX_EXPR_DEPTH>0 - pNew->nHeight = 1; -#endif - } - return pNew; -} - /* ** Attach subtrees pLeft and pRight to the Expr node pRoot. ** @@ -112945,7 +112603,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ ){ sqlite3ExprDeferredDelete(pParse, pLeft); sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3ExprInt32(db, 0); + return sqlite3Expr(db, TK_INTEGER, "0"); }else{ return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); } @@ -113070,9 +112728,7 @@ SQLITE_PRIVATE void sqlite3ExprFunctionUsable( ){ assert( !IN_RENAME_OBJECT ); assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 ); - if( ExprHasProperty(pExpr, EP_FromDDL) - || pParse->prepFlags & SQLITE_PREPARE_FROM_DDL - ){ + if( ExprHasProperty(pExpr, EP_FromDDL) ){ if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 || (pParse->db->flags & SQLITE_TrustedSchema)==0 ){ @@ -113768,7 +113424,9 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); pNew->iLimit = 0; pNew->iOffset = 0; - pNew->selFlags = p->selFlags; + pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; pNew->pWith = sqlite3WithDup(db, p->pWith); #ifndef SQLITE_OMIT_WINDOWFUNC @@ -114420,7 +114078,7 @@ static int exprIsConst(Parse *pParse, Expr *p, int initFlag){ /* ** Walk an expression tree. Return non-zero if the expression is constant -** or return zero if the expression involves variables or function calls. +** and 0 if it involves variables or function calls. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is @@ -115210,7 +114868,6 @@ SQLITE_PRIVATE int sqlite3FindInIndex( */ u32 savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; - int bloomOk = (inFlags & IN_INDEX_MEMBERSHIP)!=0; eType = IN_INDEX_EPH; if( inFlags & IN_INDEX_LOOP ){ pParse->nQueryLoop = 0; @@ -115218,13 +114875,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex( *prRhsHasNull = rMayHaveNull = ++pParse->nMem; } assert( pX->op==TK_IN ); - if( !bloomOk - && ExprUseXSelect(pX) - && (pX->x.pSelect->selFlags & SF_ClonedRhsIn)!=0 - ){ - bloomOk = 1; - } - sqlite3CodeRhsOfIN(pParse, pX, iTab, bloomOk); + sqlite3CodeRhsOfIN(pParse, pX, iTab); if( rMayHaveNull ){ sqlite3SetHasNullFlag(v, iTab, rMayHaveNull); } @@ -115382,8 +115033,7 @@ static int findCompatibleInRhsSubrtn( SQLITE_PRIVATE void sqlite3CodeRhsOfIN( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The IN operator */ - int iTab, /* Use this cursor number */ - int allowBloom /* True to allow the use of a Bloom filter */ + int iTab /* Use this cursor number */ ){ int addrOnce = 0; /* Address of the OP_Once instruction at top */ int addr; /* Address of OP_OpenEphemeral instruction */ @@ -115505,10 +115155,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( sqlite3SelectDestInit(&dest, SRT_Set, iTab); dest.zAffSdst = exprINAffinity(pParse, pExpr); pSelect->iLimit = 0; - if( addrOnce - && allowBloom - && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) - ){ + if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ int regBloom = ++pParse->nMem; addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom); VdbeComment((v, "Bloom filter")); @@ -115729,7 +115376,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ || (pLeft->u.iValue!=1 && pLeft->u.iValue!=0) ){ sqlite3 *db = pParse->db; - pLimit = sqlite3ExprInt32(db, 0); + pLimit = sqlite3Expr(db, TK_INTEGER, "0"); if( pLimit ){ pLimit->affExpr = SQLITE_AFF_NUMERIC; pLimit = sqlite3PExpr(pParse, TK_NE, @@ -115740,7 +115387,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ } }else{ /* If there is no pre-existing limit add a limit of 1 */ - pLimit = sqlite3ExprInt32(pParse->db, 1); + pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1"); pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0); } pSel->iLimit = 0; @@ -116001,9 +115648,8 @@ static void sqlite3ExprCodeIN( if( ExprHasProperty(pExpr, EP_Subrtn) ){ const VdbeOp *pOp = sqlite3VdbeGetOp(v, pExpr->y.sub.iAddr); assert( pOp->opcode==OP_Once || pParse->nErr ); - if( pOp->p3>0 ){ /* tag-202407032019 */ - assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) - || pParse->nErr ); + if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */ + assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ); sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse, rLhs, nVector); VdbeCoverage(v); } @@ -116093,7 +115739,7 @@ static void sqlite3ExprCodeIN( static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ if( ALWAYS(z!=0) ){ double value; - sqlite3AtoF(z, &value); + sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ if( negateFlag ) value = -value; sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL); @@ -119194,10 +118840,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ if( pIEpr==0 ) break; if( NEVER(!ExprUseYTab(pExpr)) ) break; for(i=0; inSrc; i++){ - if( pSrcList->a[i].iCursor==pIEpr->iDataCur ){ - testcase( i>0 ); - break; - } + if( pSrcList->a[0].iCursor==pIEpr->iDataCur ) break; } if( i>=pSrcList->nSrc ) break; if( NEVER(pExpr->pAggInfo!=0) ) break; /* Resolved by outer context */ @@ -119986,7 +119629,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); assert( sqlite3BtreeHoldsAllMutexes(db) ); - if( NEVER(db->mallocFailed) ) goto exit_begin_add_column; + if( db->mallocFailed ) goto exit_begin_add_column; pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_begin_add_column; @@ -120058,7 +119701,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ ** Or, if pTab is not a view or virtual table, zero is returned. */ #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) -static int isRealTable(Parse *pParse, Table *pTab, int iOp){ +static int isRealTable(Parse *pParse, Table *pTab, int bDrop){ const char *zType = 0; #ifndef SQLITE_OMIT_VIEW if( IsView(pTab) ){ @@ -120071,12 +119714,9 @@ static int isRealTable(Parse *pParse, Table *pTab, int iOp){ } #endif if( zType ){ - const char *azMsg[] = { - "rename columns of", "drop column from", "edit constraints of" - }; - assert( iOp>=0 && iOpzName + (bDrop ? "drop column from" : "rename columns of"), + zType, pTab->zName ); return 1; } @@ -120547,25 +120187,6 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){ return pBest; } -/* -** Set the error message of the context passed as the first argument to -** the result of formatting zFmt using printf() style formatting. -*/ -static void errorMPrintf(sqlite3_context *pCtx, const char *zFmt, ...){ - sqlite3 *db = sqlite3_context_db_handle(pCtx); - char *zErr = 0; - va_list ap; - va_start(ap, zFmt); - zErr = sqlite3VMPrintf(db, zFmt, ap); - va_end(ap); - if( zErr ){ - sqlite3_result_error(pCtx, zErr, -1); - sqlite3DbFree(db, zErr); - }else{ - sqlite3_result_error_nomem(pCtx); - } -} - /* ** An error occurred while parsing or otherwise processing a database ** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an @@ -120863,8 +120484,8 @@ static int renameResolveTrigger(Parse *pParse){ sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); if( pParse->nErr ) rc = pParse->rc; } - if( rc==SQLITE_OK && pStep->pSrc ){ - SrcList *pSrc = sqlite3SrcListDup(db, pStep->pSrc, 0); + if( rc==SQLITE_OK && pStep->zTarget ){ + SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); if( pSrc ){ Select *pSel = sqlite3SelectNew( pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 @@ -120892,10 +120513,10 @@ static int renameResolveTrigger(Parse *pParse){ pSel->pSrc = 0; sqlite3SelectDelete(db, pSel); } - if( ALWAYS(pStep->pSrc) ){ + if( pStep->pFrom ){ int i; - for(i=0; ipSrc->nSrc && rc==SQLITE_OK; i++){ - SrcItem *p = &pStep->pSrc->a[i]; + for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){ + SrcItem *p = &pStep->pFrom->a[i]; if( p->fg.isSubquery ){ assert( p->u4.pSubq!=0 ); sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0); @@ -120964,13 +120585,13 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); } - if( pStep->pSrc ){ + if( pStep->pFrom ){ int i; - SrcList *pSrc = pStep->pSrc; - for(i=0; inSrc; i++){ - if( pSrc->a[i].fg.isSubquery ){ - assert( pSrc->a[i].u4.pSubq!=0 ); - sqlite3WalkSelect(pWalker, pSrc->a[i].u4.pSubq->pSelect); + SrcList *pFrom = pStep->pFrom; + for(i=0; inSrc; i++){ + if( pFrom->a[i].fg.isSubquery ){ + assert( pFrom->a[i].u4.pSubq!=0 ); + sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect); } } } @@ -121141,8 +120762,8 @@ static void renameColumnFunc( if( rc!=SQLITE_OK ) goto renameColumnFunc_done; for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->pSrc ){ - Table *pTarget = sqlite3LocateTableItem(&sParse, 0, &pStep->pSrc->a[0]); + if( pStep->zTarget ){ + Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); if( pTarget==pTab ){ if( pStep->pUpsert ){ ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; @@ -121154,6 +120775,7 @@ static void renameColumnFunc( } } + /* Find tokens to edit in UPDATE OF clause */ if( sParse.pTriggerTab==pTab ){ renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); @@ -121355,10 +120977,13 @@ static void renameTableFunc( if( rc==SQLITE_OK ){ renameWalkTrigger(&sWalker, pTrigger); for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ - if( pStep->pSrc ){ + if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ + renameTokenFind(&sParse, &sCtx, pStep->zTarget); + } + if( pStep->pFrom ){ int i; - for(i=0; ipSrc->nSrc; i++){ - SrcItem *pItem = &pStep->pSrc->a[i]; + for(i=0; ipFrom->nSrc; i++){ + SrcItem *pItem = &pStep->pFrom->a[i]; if( 0==sqlite3_stricmp(pItem->zName, zOld) ){ renameTokenFind(&sParse, &sCtx, pItem->zName); } @@ -121605,57 +121230,6 @@ static void renameTableTest( #endif } - -/* -** Return the number of bytes until the end of the next non-whitespace and -** non-comment token. For the purpose of this function, a "(" token includes -** all of the bytes through and including the matching ")", or until the -** first illegal token, whichever comes first. -** -** Write the token type into *piToken. -** -** The value returned is the number of bytes in the token itself plus -** the number of bytes of leading whitespace and comments skipped plus -** all bytes through the next matching ")" if the token is TK_LP. -** -** Example: (Note: '.' used in place of '*' in the example z[] text) -** -** ,--------- *piToken := TK_RP -** v -** z[] = " /.comment./ --comment\n (two three four) five" -** | | -** |<-------------------------------------->| -** | -** `--- return value -*/ -static int getConstraintToken(const u8 *z, int *piToken){ - int iOff = 0; - int t = 0; - do { - iOff += sqlite3GetToken(&z[iOff], &t); - }while( t==TK_SPACE || t==TK_COMMENT ); - - *piToken = t; - - if( t==TK_LP ){ - int nNest = 1; - while( nNest>0 ){ - iOff += sqlite3GetToken(&z[iOff], &t); - if( t==TK_LP ){ - nNest++; - }else if( t==TK_RP ){ - t = TK_LP; - nNest--; - }else if( t==TK_ILLEGAL ){ - break; - } - } - } - - *piToken = t; - return iOff; -} - /* ** The implementation of internal UDF sqlite_drop_column(). ** @@ -121700,24 +121274,15 @@ static void dropColumnFunc( goto drop_column_done; } + pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); if( iColnCol-1 ){ RenameToken *pEnd; - pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName); pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName); zEnd = (const char*)pEnd->t.z; }else{ - int eTok; assert( IsOrdinaryTable(pTab) ); - assert( iCol!=0 ); - /* Point pCol->t.z at the "," immediately preceding the definition of - ** the column being dropped. To do this, start at the name of the - ** previous column, and tokenize until the next ",". */ - pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol-1].zCnName); - do { - pCol->t.z += getConstraintToken((const u8*)pCol->t.z, &eTok); - }while( eTok!=TK_COMMA ); - pCol->t.z--; zEnd = (const char*)&zSql[pTab->u.tab.addColOffset]; + while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--; } zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd); @@ -121886,651 +121451,6 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T sqlite3SrcListDelete(db, pSrc); } -/* -** Return the number of bytes of leading whitespace/comments in string z[]. -*/ -static int getWhitespace(const u8 *z){ - int nRet = 0; - while( 1 ){ - int t = 0; - int n = sqlite3GetToken(&z[nRet], &t); - if( t!=TK_SPACE && t!=TK_COMMENT ) break; - nRet += n; - } - return nRet; -} - - -/* -** Argument z points into the body of a constraint - specifically the -** second token of the constraint definition. For a named constraint, -** z points to the first token past the CONSTRAINT keyword. For an -** unnamed NOT NULL constraint, z points to the first byte past the NOT -** keyword. -** -** Return the number of bytes until the end of the constraint. -*/ -static int getConstraint(const u8 *z){ - int iOff = 0; - int t = 0; - - /* Now, the current constraint proceeds until the next occurence of one - ** of the following tokens: - ** - ** CONSTRAINT, PRIMARY, NOT, UNIQUE, CHECK, DEFAULT, - ** COLLATE, REFERENCES, FOREIGN, GENERATED, AS, RP, or COMMA - ** - ** Also exit the loop if ILLEGAL turns up. - */ - while( 1 ){ - int n = getConstraintToken(&z[iOff], &t); - if( t==TK_CONSTRAINT || t==TK_PRIMARY || t==TK_NOT || t==TK_UNIQUE - || t==TK_CHECK || t==TK_DEFAULT || t==TK_COLLATE || t==TK_REFERENCES - || t==TK_FOREIGN || t==TK_RP || t==TK_COMMA || t==TK_ILLEGAL - || t==TK_AS || t==TK_GENERATED - ){ - break; - } - iOff += n; - } - - return iOff; -} - -/* -** Compare two constraint names. -** -** Summary: *pRes := zQuote != zCmp -** -** Details: -** Compare the (possibly quoted) constraint name zQuote[0..nQuote-1] -** against zCmp[]. Write zero into *pRes if they are the same and -** non-zero if they differ. Normally return SQLITE_OK, except if there -** is an OOM, set the OOM error condition on ctx and return SQLITE_NOMEM. -*/ -static int quotedCompare( - sqlite3_context *ctx, /* Function context on which to report errors */ - int t, /* Token type */ - const u8 *zQuote, /* Possibly quoted text. Not zero-terminated. */ - int nQuote, /* Length of zQuote in bytes */ - const u8 *zCmp, /* Zero-terminated, unquoted name to compare against */ - int *pRes /* OUT: Set to 0 if equal, non-zero if unequal */ -){ - char *zCopy = 0; /* De-quoted, zero-terminated copy of zQuote[] */ - - if( t==TK_ILLEGAL ){ - *pRes = 1; - return SQLITE_OK; - } - zCopy = sqlite3MallocZero(nQuote+1); - if( zCopy==0 ){ - sqlite3_result_error_nomem(ctx); - return SQLITE_NOMEM_BKPT; - } - memcpy(zCopy, zQuote, nQuote); - sqlite3Dequote(zCopy); - *pRes = sqlite3_stricmp((const char*)zCopy, (const char*)zCmp); - sqlite3_free(zCopy); - return SQLITE_OK; -} - -/* -** zSql[] is a CREATE TABLE statement, supposedly. Find the offset -** into zSql[] of the first character past the first "(" and write -** that offset into *piOff and return SQLITE_OK. Or, if not found, -** set the SQLITE_CORRUPT error code and return SQLITE_ERROR. -*/ -static int skipCreateTable(sqlite3_context *ctx, const u8 *zSql, int *piOff){ - int iOff = 0; - - if( zSql==0 ) return SQLITE_ERROR; - - /* Jump past the "CREATE TABLE" bit. */ - while( 1 ){ - int t = 0; - iOff += sqlite3GetToken(&zSql[iOff], &t); - if( t==TK_LP ) break; - if( t==TK_ILLEGAL ){ - sqlite3_result_error_code(ctx, SQLITE_CORRUPT_BKPT); - return SQLITE_ERROR; - } - } - - *piOff = iOff; - return SQLITE_OK; -} - -/* -** Internal SQL function sqlite3_drop_constraint(): Given an input -** CREATE TABLE statement, return a revised CREATE TABLE statement -** with a constraint removed. Two forms, depending on the datatype -** of argv[2]: -** -** sqlite_drop_constraint(SQL, INT) -- Omit NOT NULL from the INT-th column -** sqlite_drop_constraint(SQL, TEXT) -- OMIT constraint with name TEXT -** -** In the first case, the left-most column is 0. -*/ -static void dropConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const u8 *zSql = sqlite3_value_text(argv[0]); - const u8 *zCons = 0; - int iNotNull = -1; - int ii; - int iOff = 0; - int iStart = 0; - int iEnd = 0; - char *zNew = 0; - int t = 0; - sqlite3 *db; - UNUSED_PARAMETER(NotUsed); - - if( zSql==0 ) return; - - /* Jump past the "CREATE TABLE" bit. */ - if( skipCreateTable(ctx, zSql, &iOff) ) return; - - if( sqlite3_value_type(argv[1])==SQLITE_INTEGER ){ - iNotNull = sqlite3_value_int(argv[1]); - }else{ - zCons = sqlite3_value_text(argv[1]); - } - - /* Search for the named constraint within column definitions. */ - for(ii=0; iEnd==0; ii++){ - - /* Now parse the column or table constraint definition. Search - ** for the token CONSTRAINT if this is a DROP CONSTRAINT command, or - ** NOT in the right column if this is a DROP NOT NULL. */ - while( 1 ){ - iStart = iOff; - iOff += getConstraintToken(&zSql[iOff], &t); - if( t==TK_CONSTRAINT && (zCons || iNotNull==ii) ){ - /* Check if this is the constraint we are searching for. */ - int nTok = 0; - int cmp = 1; - - /* Skip past any whitespace. */ - iOff += getWhitespace(&zSql[iOff]); - - /* Compare the next token - which may be quoted - with the name of - ** the constraint being dropped. */ - nTok = getConstraintToken(&zSql[iOff], &t); - if( zCons ){ - if( quotedCompare(ctx, t, &zSql[iOff], nTok, zCons, &cmp) ) return; - } - iOff += nTok; - - /* The next token is usually the first token of the constraint - ** definition. This is enough to tell the type of the constraint - - ** TK_NOT means it is a NOT NULL, TK_CHECK a CHECK constraint etc. - ** - ** There is also the chance that the next token is TK_CONSTRAINT - ** (or TK_DEFAULT or TK_COLLATE), for example if a table has been - ** created as follows: - ** - ** CREATE TABLE t1(cols, CONSTRAINT one CONSTRAINT two NOT NULL); - ** - ** In this case, allow the "CONSTRAINT one" bit to be dropped by - ** this command if that is what is requested, or to advance to - ** the next iteration of the loop with &zSql[iOff] still pointing - ** to the CONSTRAINT keyword. */ - nTok = getConstraintToken(&zSql[iOff], &t); - if( t==TK_CONSTRAINT || t==TK_DEFAULT || t==TK_COLLATE - || t==TK_COMMA || t==TK_RP || t==TK_GENERATED || t==TK_AS - ){ - t = TK_CHECK; - }else{ - iOff += nTok; - iOff += getConstraint(&zSql[iOff]); - } - - if( cmp==0 || (iNotNull>=0 && t==TK_NOT) ){ - if( t!=TK_NOT && t!=TK_CHECK ){ - errorMPrintf(ctx, "constraint may not be dropped: %s", zCons); - return; - } - iEnd = iOff; - break; - } - - }else if( t==TK_NOT && iNotNull==ii ){ - iEnd = iOff + getConstraint(&zSql[iOff]); - break; - }else if( t==TK_RP || t==TK_ILLEGAL ){ - iEnd = -1; - break; - }else if( t==TK_COMMA ){ - break; - } - } - } - - /* If the constraint has not been found it is an error. */ - if( iEnd<=0 ){ - if( zCons ){ - errorMPrintf(ctx, "no such constraint: %s", zCons); - }else{ - /* SQLite follows postgres in that a DROP NOT NULL on a column that is - ** not NOT NULL is not an error. So just return the original SQL here. */ - sqlite3_result_text(ctx, (const char*)zSql, -1, SQLITE_TRANSIENT); - } - }else{ - - /* Figure out if an extra space should be inserted after the constraint - ** is removed. And if an additional comma preceding the constraint - ** should be removed. */ - const char *zSpace = " "; - iEnd += getWhitespace(&zSql[iEnd]); - sqlite3GetToken(&zSql[iEnd], &t); - if( t==TK_RP || t==TK_COMMA ){ - zSpace = ""; - if( zSql[iStart-1]==',' ) iStart--; - } - - db = sqlite3_context_db_handle(ctx); - zNew = sqlite3MPrintf(db, "%.*s%s%s", iStart, zSql, zSpace, &zSql[iEnd]); - sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC); - } -} - -/* -** Internal SQL function: -** -** sqlite_add_constraint(SQL, CONSTRAINT-TEXT, ICOL) -** -** SQL is a CREATE TABLE statement. Return a modified version of -** SQL that adds CONSTRAINT-TEXT at the end of the ICOL-th column -** definition. (The left-most column defintion is 0.) -*/ -static void addConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const u8 *zSql = sqlite3_value_text(argv[0]); - const char *zCons = (const char*)sqlite3_value_text(argv[1]); - int iCol = sqlite3_value_int(argv[2]); - int iOff = 0; - int ii; - char *zNew = 0; - int t = 0; - sqlite3 *db; - UNUSED_PARAMETER(NotUsed); - - if( skipCreateTable(ctx, zSql, &iOff) ) return; - - for(ii=0; ii<=iCol || (iCol<0 && t!=TK_RP); ii++){ - iOff += getConstraintToken(&zSql[iOff], &t); - while( 1 ){ - int nTok = getConstraintToken(&zSql[iOff], &t); - if( t==TK_COMMA || t==TK_RP ) break; - if( t==TK_ILLEGAL ){ - sqlite3_result_error_code(ctx, SQLITE_CORRUPT_BKPT); - return; - } - iOff += nTok; - } - } - - iOff += getWhitespace(&zSql[iOff]); - - db = sqlite3_context_db_handle(ctx); - if( iCol<0 ){ - zNew = sqlite3MPrintf(db, "%.*s, %s%s", iOff, zSql, zCons, &zSql[iOff]); - }else{ - zNew = sqlite3MPrintf(db, "%.*s %s%s", iOff, zSql, zCons, &zSql[iOff]); - } - sqlite3_result_text(ctx, zNew, -1, SQLITE_DYNAMIC); -} - -/* -** Find a column named pCol in table pTab. If successful, set output -** parameter *piCol to the index of the column in the table and return -** SQLITE_OK. Otherwise, set *piCol to -1 and return an SQLite error -** code. -*/ -static int alterFindCol(Parse *pParse, Table *pTab, Token *pCol, int *piCol){ - sqlite3 *db = pParse->db; - char *zName = sqlite3NameFromToken(db, pCol); - int rc = SQLITE_NOMEM; - int iCol = -1; - - if( zName ){ - iCol = sqlite3ColumnIndex(pTab, zName); - if( iCol<0 ){ - sqlite3ErrorMsg(pParse, "no such column: %s", zName); - rc = SQLITE_ERROR; - }else{ - rc = SQLITE_OK; - } - } - -#ifndef SQLITE_OMIT_AUTHORIZATION - if( rc==SQLITE_OK ){ - const char *zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; - const char *zCol = pTab->aCol[iCol].zCnName; - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){ - pTab = 0; - } - } -#endif - - sqlite3DbFree(db, zName); - *piCol = iCol; - return rc; -} - - -/* -** Find the table named by the first entry in source list pSrc. If successful, -** return a pointer to the Table structure and set output variable (*pzDb) -** to point to the name of the database containin the table (i.e. "main", -** "temp" or the name of an attached database). -** -** If the table cannot be located, return NULL. The value of the two output -** parameters is undefined in this case. -*/ -static Table *alterFindTable( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* Name of the table to look for */ - int *piDb, /* OUT: write the iDb here */ - const char **pzDb, /* OUT: write name of schema here */ - int bAuth /* Do ALTER TABLE authorization checks if true */ -){ - sqlite3 *db = pParse->db; - Table *pTab = 0; - assert( sqlite3BtreeHoldsAllMutexes(db) ); - pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); - if( pTab ){ - int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - *pzDb = db->aDb[iDb].zDbSName; - *piDb = iDb; - - if( SQLITE_OK!=isRealTable(pParse, pTab, 2) - || SQLITE_OK!=isAlterableTable(pParse, pTab) - ){ - pTab = 0; - } - } -#ifndef SQLITE_OMIT_AUTHORIZATION - if( pTab && bAuth ){ - if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, *pzDb, pTab->zName, 0) ){ - pTab = 0; - } - } -#endif - sqlite3SrcListDelete(db, pSrc); - return pTab; -} - -/* -** Generate bytecode for one of: -** -** (1) ALTER TABLE pSrc DROP CONSTRAINT pCons -** (2) ALTER TABLE pSrc ALTER pCol DROP NOT NULL -** -** One of pCons and pCol must be NULL and the other non-null. -*/ -SQLITE_PRIVATE void sqlite3AlterDropConstraint( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* The table being altered */ - Token *pCons, /* Name of the constraint to drop */ - Token *pCol /* Name of the column from which to remove the NOT NULL */ -){ - sqlite3 *db = pParse->db; - Table *pTab = 0; - int iDb = 0; - const char *zDb = 0; - char *zArg = 0; - - assert( (pCol==0)!=(pCons==0) ); - assert( pSrc->nSrc==1 ); - pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0); - if( !pTab ) return; - - if( pCons ){ - zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z); - }else{ - int iCol; - if( alterFindCol(pParse, pTab, pCol, &iCol) ) return; - zArg = sqlite3MPrintf(db, "%d", iCol); - } - - /* Edit the SQL for the named table. */ - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_drop_constraint(sql, %s) " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase" - , zDb, zArg, pTab->zName - ); - sqlite3DbFree(db, zArg); - - /* Finally, reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons); -} - -/* -** The implementation of SQL function sqlite_fail(MSG). This takes a single -** argument, and returns it as an error message with the error code set to -** SQLITE_CONSTRAINT. -*/ -static void failConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const char *zText = (const char*)sqlite3_value_text(argv[0]); - int err = sqlite3_value_int(argv[1]); - (void)NotUsed; - sqlite3_result_error(ctx, zText, -1); - sqlite3_result_error_code(ctx, err); -} - -/* -** Buffer pCons, which is nCons bytes in size, contains the text of a -** NOT NULL or CHECK constraint that will be inserted into a CREATE TABLE -** statement. If successful, this function returns the size of the buffer in -** bytes not including any trailing whitespace or "--" style comments. Or, -** if an OOM occurs, it returns 0 and sets db->mallocFailed to true. -** -** C-style comments at the end are preserved. "--" style comments are -** removed because the comment terminator might be \000, and we are about -** to insert the pCons[] text into the middle of a larger string, and that -** will have the effect of removing the comment terminator and messing up -** the syntax. -*/ -static int alterRtrimConstraint( - sqlite3 *db, /* used to record OOM error */ - const char *pCons, /* Buffer containing constraint */ - int nCons /* Size of pCons in bytes */ -){ - u8 *zTmp = (u8*)sqlite3MPrintf(db, "%.*s", nCons, pCons); - int iOff = 0; - int iEnd = 0; - - if( zTmp==0 ) return 0; - - while( 1 ){ - int t = 0; - int nToken = sqlite3GetToken(&zTmp[iOff], &t); - if( t==TK_ILLEGAL ) break; - if( t!=TK_SPACE && (t!=TK_COMMENT || zTmp[iOff]!='-') ){ - iEnd = iOff+nToken; - } - iOff += nToken; - } - - sqlite3DbFree(db, zTmp); - return iEnd; -} - -/* -** Prepare a statement of the form: -** -** ALTER TABLE pSrc ALTER pCol SET NOT NULL -*/ -SQLITE_PRIVATE void sqlite3AlterSetNotNull( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* Name of the table being altered */ - Token *pCol, /* Name of the column to add a NOT NULL constraint to */ - Token *pFirst /* The NOT token of the NOT NULL constraint text */ -){ - Table *pTab = 0; - int iCol = 0; - int iDb = 0; - const char *zDb = 0; - const char *pCons = 0; - int nCons = 0; - - /* Look up the table being altered. */ - assert( pSrc->nSrc==1 ); - pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 0); - if( !pTab ) return; - - /* Find the column being altered. */ - if( alterFindCol(pParse, pTab, pCol, &iCol) ){ - return; - } - - /* Find the length in bytes of the constraint definition */ - pCons = pFirst->z; - nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons); - - /* Search for a constraint violation. Throw an exception if one is found. */ - sqlite3NestedParse(pParse, - "SELECT sqlite_fail('constraint failed', %d) " - "FROM %Q.%Q AS x WHERE x.%.*s IS NULL", - SQLITE_CONSTRAINT, zDb, pTab->zName, (int)pCol->n, pCol->z - ); - - /* Edit the SQL for the named table. */ - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_add_constraint(sqlite_drop_constraint(sql, %d), %.*Q, %d) " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase" - , zDb, iCol, nCons, pCons, iCol, pTab->zName - ); - - /* Finally, reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons); -} - -/* -** Implementation of internal SQL function: -** -** sqlite_find_constraint(SQL, CONSTRAINT-NAME) -** -** This function returns true if the SQL passed as the first argument is a -** CREATE TABLE that contains a constraint with the name CONSTRAINT-NAME, -** or false otherwise. -*/ -static void findConstraintFunc( - sqlite3_context *ctx, - int NotUsed, - sqlite3_value **argv -){ - const u8 *zSql = 0; - const u8 *zCons = 0; - int iOff = 0; - int t = 0; - - (void)NotUsed; - zSql = sqlite3_value_text(argv[0]); - zCons = sqlite3_value_text(argv[1]); - - if( zSql==0 || zCons==0 ) return; - while( t!=TK_LP && t!=TK_ILLEGAL ){ - iOff += sqlite3GetToken(&zSql[iOff], &t); - } - - while( 1 ){ - iOff += getConstraintToken(&zSql[iOff], &t); - if( t==TK_CONSTRAINT ){ - int nTok = 0; - int cmp = 0; - iOff += getWhitespace(&zSql[iOff]); - nTok = getConstraintToken(&zSql[iOff], &t); - if( quotedCompare(ctx, t, &zSql[iOff], nTok, zCons, &cmp) ) return; - if( cmp==0 ){ - sqlite3_result_int(ctx, 1); - return; - } - }else if( t==TK_ILLEGAL ){ - break; - } - } - - sqlite3_result_int(ctx, 0); -} - -/* -** Generate bytecode to implement: -** -** ALTER TABLE pSrc ADD [CONSTRAINT pName] CHECK(pExpr) -** -** Any "ON CONFLICT" text that occurs after the "CHECK(...)", up -** until pParse->sLastToken, is included as part of the new constraint. -*/ -SQLITE_PRIVATE void sqlite3AlterAddConstraint( - Parse *pParse, /* Parse context */ - SrcList *pSrc, /* Table to add constraint to */ - Token *pFirst, /* First token of new constraint */ - Token *pName, /* Name of new constraint. NULL if name omitted. */ - const char *pExpr, /* Text of CHECK expression */ - int nExpr /* Size of pExpr in bytes */ -){ - Table *pTab = 0; /* Table identified by pSrc */ - int iDb = 0; /* Which schema does pTab live in */ - const char *zDb = 0; /* Name of the schema in which pTab lives */ - const char *pCons = 0; /* Text of the constraint */ - int nCons; /* Bytes of text to use from pCons[] */ - - /* Look up the table being altered. */ - assert( pSrc->nSrc==1 ); - pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1); - if( !pTab ) return; - - /* If this new constraint has a name, check that it is not a duplicate of - ** an existing constraint. It is an error if it is. */ - if( pName ){ - char *zName = sqlite3NameFromToken(pParse->db, pName); - - sqlite3NestedParse(pParse, - "SELECT sqlite_fail('constraint %q already exists', %d) " - "FROM \"%w\"." LEGACY_SCHEMA_TABLE " " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase " - "AND sqlite_find_constraint(sql, %Q)", - zName, SQLITE_ERROR, zDb, pTab->zName, zName - ); - sqlite3DbFree(pParse->db, zName); - } - - /* Search for a constraint violation. Throw an exception if one is found. */ - sqlite3NestedParse(pParse, - "SELECT sqlite_fail('constraint failed', %d) " - "FROM %Q.%Q WHERE (%.*s) IS NOT TRUE", - SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr - ); - - /* Edit the SQL for the named table. */ - pCons = pFirst->z; - nCons = alterRtrimConstraint(pParse->db, pCons, pParse->sLastToken.z - pCons); - - sqlite3NestedParse(pParse, - "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET " - "sql = sqlite_add_constraint(sql, %.*Q, -1) " - "WHERE type='table' AND tbl_name=%Q COLLATE nocase" - , zDb, nCons, pCons, pTab->zName - ); - - /* Finally, reload the database schema. */ - renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons); -} - /* ** Register built-in functions used to help implement ALTER TABLE */ @@ -122541,10 +121461,6 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void){ INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest), INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc), INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc), - INTERNAL_FUNCTION(sqlite_drop_constraint,2, dropConstraintFunc), - INTERNAL_FUNCTION(sqlite_fail, 2, failConstraintFunc), - INTERNAL_FUNCTION(sqlite_add_constraint, 3, addConstraintFunc), - INTERNAL_FUNCTION(sqlite_find_constraint,2, findConstraintFunc), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } @@ -125165,7 +124081,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep( if( sqlite3WalkSelect(&pFix->w, pStep->pSelect) || sqlite3WalkExpr(&pFix->w, pStep->pWhere) || sqlite3WalkExprList(&pFix->w, pStep->pExprList) - || sqlite3FixSrcList(pFix, pStep->pSrc) + || sqlite3FixSrcList(pFix, pStep->pFrom) ){ return 1; } @@ -125272,7 +124188,7 @@ SQLITE_API int sqlite3_set_authorizer( sqlite3_mutex_enter(db->mutex); db->xAuth = (sqlite3_xauth)xAuth; db->pAuthArg = pArg; - sqlite3ExpirePreparedStatements(db, 1); + if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -125943,7 +124859,6 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem( const char *zDb; if( p->fg.fixedSchema ){ int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema); - assert( iDb>=0 && iDbdb->nDb ); zDb = pParse->db->aDb[iDb].zDbSName; }else{ assert( !p->fg.isSubquery ); @@ -127517,8 +126432,8 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ ** The estimate is conservative. It might be larger that what is ** really needed. */ -static i64 identLength(const char *z){ - i64 n; +static int identLength(const char *z){ + int n; for(n=0; *z; n++, z++){ if( *z=='"' ){ n++; } } @@ -128028,14 +126943,13 @@ SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){ ** restored to its original value prior to this routine returning. */ SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ - const char *zTail; /* Pointer to the last "_" in zName */ + char *zTail; /* Pointer to the last "_" in zName */ Table *pTab; /* Table that zName is a shadow of */ - char *zCopy; zTail = strrchr(zName, '_'); if( zTail==0 ) return 0; - zCopy = sqlite3DbStrNDup(db, zName, (int)(zTail-zName)); - pTab = zCopy ? sqlite3FindTable(db, zCopy, 0) : 0; - sqlite3DbFree(db, zCopy); + *zTail = 0; + pTab = sqlite3FindTable(db, zName, 0); + *zTail = '_'; if( pTab==0 ) return 0; if( !IsVirtual(pTab) ) return 0; return sqlite3IsShadowTableOf(db, pTab, zName); @@ -128188,7 +127102,6 @@ SQLITE_PRIVATE void sqlite3EndTable( convertToWithoutRowidTable(pParse, p); } iDb = sqlite3SchemaToIndex(db, p->pSchema); - assert( iDb>=0 && iDb<=db->nDb ); #ifndef SQLITE_OMIT_CHECK /* Resolve names in all CHECK constraint expressions. @@ -128484,7 +127397,6 @@ SQLITE_PRIVATE void sqlite3CreateView( sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); - assert( iDb>=0 && iDbnDb ); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; @@ -130081,7 +128993,6 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists goto exit_drop_index; } iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); - assert( iDb>=0 && iDbnDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; @@ -131916,7 +130827,7 @@ static int vtabIsReadOnly(Parse *pParse, Table *pTab){ ** * Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS ** virtual tables if PRAGMA trusted_schema=ON. */ - if( (pParse->pToplevel!=0 || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL)) + if( pParse->pToplevel!=0 && pTab->u.vtab.p->eVtabRisk > ((pParse->db->flags & SQLITE_TrustedSchema)!=0) ){ @@ -132754,6 +131665,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( &iPartIdxLabel, pPrior, r1); sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1, pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn); + sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */ sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel); pPrior = pIdx; } @@ -133328,7 +132240,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3_result_error_nomem(context); return; } - sqlite3AtoF(zBuf, &r); + sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); sqlite3_free(zBuf); } sqlite3_result_double(context, r); @@ -133966,7 +132878,7 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int sqlite3_str_appendf(pStr, "%!0.15g", r1); zVal = sqlite3_str_value(pStr); if( zVal ){ - sqlite3AtoF(zVal, &r2); + sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); if( r1!=r2 ){ sqlite3_str_reset(pStr); sqlite3_str_appendf(pStr, "%!0.20e", r1); @@ -134063,7 +132975,7 @@ static void unistrFunc( } i = j = 0; while( ifuncFlags |= flags; pDef->funcFlags &= ~SQLITE_FUNC_UNSAFE; } @@ -137016,7 +135926,6 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *pTab){ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ if( p ){ TriggerStep *pStep = p->step_list; - sqlite3SrcListDelete(dbMem, pStep->pSrc); sqlite3ExprDelete(dbMem, pStep->pWhere); sqlite3ExprListDelete(dbMem, pStep->pExprList); sqlite3SelectDelete(dbMem, pStep->pSelect); @@ -137236,7 +136145,6 @@ SQLITE_PRIVATE void sqlite3FkCheck( if( !IsOrdinaryTable(pTab) ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - assert( iDb>=00 && iDbnDb ); zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the @@ -137684,14 +136592,14 @@ static Trigger *fkActionTrigger( pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ - sizeof(TriggerStep) /* Single step in trigger program */ + sizeof(TriggerStep) + /* Single step in trigger program */ + nFrom + 1 /* Space for pStep->zTarget */ ); if( pTrigger ){ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); - if( pStep->pSrc ){ - pStep->pSrc->a[0].zName = sqlite3DbStrNDup(db, zFrom, nFrom); - } + pStep->zTarget = (char *)&pStep[1]; + memcpy((char *)pStep->zTarget, zFrom, nFrom); + pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); @@ -141748,11 +140656,7 @@ struct sqlite3_api_routines { /* Version 3.51.0 and later */ int (*set_errmsg)(sqlite3*,int,const char*); int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); - /* Version 3.52.0 and later */ - void (*str_truncate)(sqlite3_str*,int); - void (*str_free)(sqlite3_str*); - int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); - int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); + }; /* @@ -142091,11 +140995,6 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.51.0 and later */ #define sqlite3_set_errmsg sqlite3_api->set_errmsg #define sqlite3_db_status64 sqlite3_api->db_status64 -/* Version 3.52.0 and later */ -#define sqlite3_str_truncate sqlite3_api->str_truncate -#define sqlite3_str_free sqlite3_api->str_free -#define sqlite3_carray_bind sqlite3_api->carray_bind -#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -142622,17 +141521,7 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_setlk_timeout, /* Version 3.51.0 and later */ sqlite3_set_errmsg, - sqlite3_db_status64, - /* Version 3.52.0 and later */ - sqlite3_str_truncate, - sqlite3_str_free, -#ifdef SQLITE_ENABLE_CARRAY - sqlite3_carray_bind, - sqlite3_carray_bind_v2 -#else - 0, - 0 -#endif + sqlite3_db_status64 }; /* True if x is the directory separator character @@ -142734,42 +141623,33 @@ static int sqlite3LoadExtension( ** entry point name "sqlite3_extension_init" was not found, then ** construct an entry point name "sqlite3_X_init" where the X is ** replaced by the lowercase value of every ASCII alphabetic - ** character in the filename after the last "/" up to the first ".", - ** and skipping the first three characters if they are "lib". + ** character in the filename after the last "/" upto the first ".", + ** and eliding the first three characters if they are "lib". ** Examples: ** ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init ** C:/lib/mathfuncs.dll ==> sqlite3_mathfuncs_init - ** - ** If that still finds no entry point, repeat a second time but this - ** time include both alphabetic and numeric characters up to the first - ** ".". Example: - ** - ** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example5_init */ if( xInit==0 && zProc==0 ){ int iFile, iEntry, c; int ncFile = sqlite3Strlen30(zFile); - int cnt = 0; zAltEntry = sqlite3_malloc64(ncFile+30); if( zAltEntry==0 ){ sqlite3OsDlClose(pVfs, handle); return SQLITE_NOMEM_BKPT; } - do{ - memcpy(zAltEntry, "sqlite3_", 8); - for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} - iFile++; - if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; - for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ - if( sqlite3Isalpha(c) || (cnt && sqlite3Isdigit(c)) ){ - zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; - } + memcpy(zAltEntry, "sqlite3_", 8); + for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){} + iFile++; + if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3; + for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){ + if( sqlite3Isalpha(c) ){ + zAltEntry[iEntry++] = (char)sqlite3UpperToLower[(unsigned)c]; } - memcpy(zAltEntry+iEntry, "_init", 6); - zEntry = zAltEntry; - xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); - }while( xInit==0 && (++cnt)<2 ); + } + memcpy(zAltEntry+iEntry, "_init", 6); + zEntry = zAltEntry; + xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); } if( xInit==0 ){ if( pzErrMsg ){ @@ -146841,8 +145721,7 @@ static void corruptSchema( static const char *azAlterType[] = { "rename", "drop column", - "add column", - "drop constraint" + "add column" }; *pData->pzErrMsg = sqlite3MPrintf(db, "error in %s %s after %s: %s", azObj[0], azObj[1], @@ -147925,7 +146804,7 @@ SQLITE_API int sqlite3_prepare16_v3( */ typedef struct DistinctCtx DistinctCtx; struct DistinctCtx { - u8 isTnct; /* 0: Not distinct. 1: DISTINCT 2: DISTINCT and ORDER BY */ + u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */ int tabTnct; /* Ephemeral table used for DISTINCT processing */ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */ @@ -148055,6 +146934,8 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->iLimit = 0; pNew->iOffset = 0; pNew->selId = ++pParse->nSelect; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = 0; if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1); pNew->pSrc = pSrc; @@ -148563,10 +147444,6 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){ pRight->fg.isOn = 1; p->selFlags |= SF_OnToWhere; } - - if( IsVirtual(pRightTab) && joinType==EP_OuterON && pRight->u1.pFuncArg ){ - p->selFlags |= SF_OnToWhere; - } } return 0; } @@ -149206,6 +148083,29 @@ static void selectInnerLoop( } switch( eDest ){ + /* In this mode, write each query result to the key of the temporary + ** table iParm. + */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT + case SRT_Union: { + int r1; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); + sqlite3ReleaseTempReg(pParse, r1); + break; + } + + /* Construct a record from the query result, but instead of + ** saving that record, use it as a key to delete elements from + ** the temporary table iParm. + */ + case SRT_Except: { + sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol); + break; + } +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + /* Store the result as data using a unique key. */ case SRT_Fifo: @@ -150318,8 +149218,8 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes( } } if( zType ){ - const i64 k = strlen(zType); - n = strlen(pCol->zCnName); + const i64 k = sqlite3Strlen30(zType); + n = sqlite3Strlen30(pCol->zCnName); pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+k+2); pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); if( pCol->zCnName ){ @@ -150492,9 +149392,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ ** function is responsible for ensuring that this structure is eventually ** freed. */ -static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){ +static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ ExprList *pOrderBy = p->pOrderBy; - int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0; + int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0; sqlite3 *db = pParse->db; KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); if( pRet ){ @@ -150627,7 +149527,7 @@ static void generateWithRecursiveQuery( regCurrent = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol); if( pOrderBy ){ - KeyInfo *pKeyInfo = multiSelectByMergeKeyInfo(pParse, p, 1); + KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1); sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0, (char*)pKeyInfo, P4_KEYINFO); destQueue.pOrderBy = pOrderBy; @@ -150636,28 +149536,8 @@ static void generateWithRecursiveQuery( } VdbeComment((v, "Queue table")); if( iDistinct ){ - /* Generate an ephemeral table used to enforce distinctness on the - ** output of the recursive part of the CTE. - */ - KeyInfo *pKeyInfo; /* Collating sequence for the result set */ - CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ - - assert( p->pNext==0 ); - assert( p->pEList!=0 ); - nCol = p->pEList->nExpr; - pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nCol, 1); - if( pKeyInfo ){ - for(i=0, apColl=pKeyInfo->aColl; idb->pDfltColl; - } - } - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iDistinct, nCol, 0, - (void*)pKeyInfo, P4_KEYINFO); - }else{ - assert( pParse->nErr>0 ); - } + p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0); + p->selFlags |= SF_UsesEphemeral; } /* Detach the ORDER BY clause from the compound SELECT */ @@ -150732,7 +149612,7 @@ static void generateWithRecursiveQuery( #endif /* SQLITE_OMIT_CTE */ /* Forward references */ -static int multiSelectByMerge( +static int multiSelectOrderBy( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest /* What to do with query results */ @@ -150881,26 +149761,12 @@ static int multiSelect( generateWithRecursiveQuery(pParse, p, &dest); }else #endif + + /* Compound SELECTs that have an ORDER BY clause are handled separately. + */ if( p->pOrderBy ){ - /* If the compound has an ORDER BY clause, then always use the merge - ** algorithm. */ - return multiSelectByMerge(pParse, p, pDest); - }else if( p->op!=TK_ALL ){ - /* If the compound is EXCEPT, INTERSECT, or UNION (anything other than - ** UNION ALL) then also always use the merge algorithm. However, the - ** multiSelectByMerge() routine requires that the compound have an - ** ORDER BY clause, and it doesn't right now. So invent one first. */ - Expr *pOne = sqlite3ExprInt32(db, 1); - p->pOrderBy = sqlite3ExprListAppend(pParse, 0, pOne); - if( pParse->nErr ) goto multi_select_end; - assert( p->pOrderBy!=0 ); - p->pOrderBy->a[0].u.x.iOrderByCol = 1; - return multiSelectByMerge(pParse, p, pDest); - }else{ - /* For a UNION ALL compound without ORDER BY, simply run the left - ** query, then run the right query */ - int addr = 0; - int nLimit = 0; /* Initialize to suppress harmless compiler warning */ + return multiSelectOrderBy(pParse, p, pDest); + }else{ #ifndef SQLITE_OMIT_EXPLAIN if( pPrior->pPrior==0 ){ @@ -150908,49 +149774,300 @@ static int multiSelect( ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); } #endif - assert( !pPrior->pLimit ); - pPrior->iLimit = p->iLimit; - pPrior->iOffset = p->iOffset; - pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0); - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); - rc = sqlite3Select(pParse, pPrior, &dest); - sqlite3ExprDelete(db, pPrior->pLimit); - pPrior->pLimit = 0; - if( rc ){ - goto multi_select_end; - } - p->pPrior = 0; - p->iLimit = pPrior->iLimit; - p->iOffset = pPrior->iOffset; - if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); - VdbeComment((v, "Jump ahead if LIMIT reached")); - if( p->iOffset ){ - sqlite3VdbeAddOp3(v, OP_OffsetLimit, - p->iLimit, p->iOffset+1, p->iOffset); - } - } - ExplainQueryPlan((pParse, 1, "UNION ALL")); - TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); - rc = sqlite3Select(pParse, p, &dest); - testcase( rc!=SQLITE_OK ); - pDelete = p->pPrior; - p->pPrior = pPrior; - p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); - if( p->pLimit - && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) - && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) - ){ - p->nSelectRow = sqlite3LogEst((u64)nLimit); - } - if( addr ){ - sqlite3VdbeJumpHere(v, addr); + + /* Generate code for the left and right SELECT statements. + */ + switch( p->op ){ + case TK_ALL: { + int addr = 0; + int nLimit = 0; /* Initialize to suppress harmless compiler warning */ + assert( !pPrior->pLimit ); + pPrior->iLimit = p->iLimit; + pPrior->iOffset = p->iOffset; + pPrior->pLimit = p->pLimit; + TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n")); + rc = sqlite3Select(pParse, pPrior, &dest); + pPrior->pLimit = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit ){ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); + VdbeComment((v, "Jump ahead if LIMIT reached")); + if( p->iOffset ){ + sqlite3VdbeAddOp3(v, OP_OffsetLimit, + p->iLimit, p->iOffset+1, p->iOffset); + } + } + ExplainQueryPlan((pParse, 1, "UNION ALL")); + TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL right...\n")); + rc = sqlite3Select(pParse, p, &dest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + if( p->pLimit + && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) + && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) + ){ + p->nSelectRow = sqlite3LogEst((u64)nLimit); + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temp table holding result */ + u8 op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit; /* Saved values of p->nLimit */ + int addr; + int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */ + SelectDest uniondest; + + + testcase( p->op==TK_EXCEPT ); + testcase( p->op==TK_UNION ); + priorOp = SRT_Union; + if( dest.eDest==priorOp ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + assert( p->pLimit==0 ); /* Not allowed on leftward elements */ + unionTab = dest.iSDParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + assert( p->pOrderBy==0 ); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + } + + + /* Code the SELECT statements to our left + */ + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION left...\n")); + rc = sqlite3Select(pParse, pPrior, &uniondest); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement + */ + if( p->op==TK_EXCEPT ){ + op = SRT_Except; + emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab); + VdbeCoverage(v); + }else{ + assert( p->op==TK_UNION ); + op = SRT_Union; + } + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + uniondest.eDest = op; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + sqlite3SelectOpName(p->op))); + TREETRACE(0x200, pParse, p, ("multiSelect EXCEPT/UNION right...\n")); + rc = sqlite3Select(pParse, p, &uniondest); + testcase( rc!=SQLITE_OK ); + assert( p->pOrderBy==0 ); + pDelete = p->pPrior; + p->pPrior = pPrior; + p->pOrderBy = 0; + if( p->op==TK_UNION ){ + p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); + } + if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass); + sqlite3ExprDelete(db, p->pLimit); + p->pLimit = pLimit; + p->iLimit = 0; + p->iOffset = 0; + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + assert( unionTab==dest.iSDParm || dest.eDest!=priorOp ); + assert( p->pEList || db->mallocFailed ); + if( dest.eDest!=priorOp && db->mallocFailed==0 ){ + int iCont, iBreak, iStart; + iBreak = sqlite3VdbeMakeLabel(pParse); + iCont = sqlite3VdbeMakeLabel(pParse); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, unionTab, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + default: assert( p->op==TK_INTERSECT ); { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit; + int addr, iLimit, iOffset; + SelectDest intersectdest; + int r1; + int emptyBypass; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; + assert( p->pOrderBy==0 ); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + findRightmost(p)->selFlags |= SF_UsesEphemeral; + assert( p->pEList ); + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT left...\n")); + rc = sqlite3Select(pParse, pPrior, &intersectdest); + if( rc ){ + goto multi_select_end; + } + + /* Initialize LIMIT counters before checking to see if the LHS + ** is empty, in case the jump is taken */ + iBreak = sqlite3VdbeMakeLabel(pParse); + computeLimitRegisters(pParse, p, iBreak); + emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v); + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + + /* Disable prior SELECTs and the LIMIT counters during the computation + ** of the RHS select */ + pLimit = p->pLimit; + iLimit = p->iLimit; + iOffset = p->iOffset; + p->pPrior = 0; + p->pLimit = 0; + p->iLimit = 0; + p->iOffset = 0; + + intersectdest.iSDParm = tab2; + ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE", + sqlite3SelectOpName(p->op))); + TREETRACE(0x400, pParse, p, ("multiSelect INTERSECT right...\n")); + rc = sqlite3Select(pParse, p, &intersectdest); + testcase( rc!=SQLITE_OK ); + pDelete = p->pPrior; + p->pPrior = pPrior; + if( p->nSelectRow>pPrior->nSelectRow ){ + p->nSelectRow = pPrior->nSelectRow; + } + sqlite3ExprDelete(db, p->pLimit); + + /* Reinstate the LIMIT counters prior to running the final intersect */ + p->pLimit = pLimit; + p->iLimit = iLimit; + p->iOffset = iOffset; + + /* Generate code to take the intersection of the two temporary + ** tables. + */ + if( rc ) break; + assert( p->pEList ); + sqlite3VdbeAddOp1(v, OP_Rewind, tab1); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); + iCont = sqlite3VdbeMakeLabel(pParse); + sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); + VdbeCoverage(v); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, tab1, + 0, 0, &dest, iCont, iBreak); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeJumpHere(v, emptyBypass); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; + } } -#ifndef SQLITE_OMIT_EXPLAIN + + #ifndef SQLITE_OMIT_EXPLAIN if( p->pNext==0 ){ ExplainQueryPlanPop(pParse); } -#endif + #endif + } + if( pParse->nErr ) goto multi_select_end; + + /* Compute collating sequences used by + ** temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. + ** + ** This section is run by the right-most SELECT statement only. + ** SELECT statements to the left always skip this part. The right-most + ** SELECT might also skip this part if it has no ORDER BY clause and + ** no temp tables are required. + */ + if( p->selFlags & SF_UsesEphemeral ){ + int i; /* Loop counter */ + KeyInfo *pKeyInfo; /* Collating sequence for the result set */ + Select *pLoop; /* For looping through SELECT statements */ + CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ + int nCol; /* Number of columns in result set */ + + assert( p->pNext==0 ); + assert( p->pEList!=0 ); + nCol = p->pEList->nExpr; + pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1); + if( !pKeyInfo ){ + rc = SQLITE_NOMEM_BKPT; + goto multi_select_end; + } + for(i=0, apColl=pKeyInfo->aColl; ipDfltColl; + } + } + + for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ + for(i=0; i<2; i++){ + int addr = pLoop->addrOpenEphm[i]; + if( addr<0 ){ + /* If [0] is unused then [1] is also unused. So we can + ** always safely abort as soon as the first unused slot is found */ + assert( pLoop->addrOpenEphm[1]<0 ); + break; + } + sqlite3VdbeChangeP2(v, addr, nCol); + sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo), + P4_KEYINFO); + pLoop->addrOpenEphm[i] = -1; + } + } + sqlite3KeyInfoUnref(pKeyInfo); } multi_select_end: @@ -150982,8 +150099,8 @@ SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ ** Code an output subroutine for a coroutine implementation of a ** SELECT statement. ** -** The data to be output is contained in an array of pIn->nSdst registers -** starting at register pIn->iSdst. pDest is where the output should +** The data to be output is contained in pIn->iSdst. There are +** pIn->nSdst columns to be output. pDest is where the output should ** be sent. ** ** regReturn is the number of the register holding the subroutine @@ -151012,8 +150129,6 @@ static int generateOutputSubroutine( int iContinue; int addr; - assert( pIn->eDest==SRT_Coroutine ); - addr = sqlite3VdbeCurrentAddr(v); iContinue = sqlite3VdbeMakeLabel(pParse); @@ -151035,60 +150150,23 @@ static int generateOutputSubroutine( */ codeOffset(v, p->iOffset, iContinue); + assert( pDest->eDest!=SRT_Exists ); + assert( pDest->eDest!=SRT_Table ); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ - case SRT_Fifo: - case SRT_DistFifo: - case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); - int iParm = pDest->iSDParm; - testcase( pDest->eDest==SRT_Table ); - testcase( pDest->eDest==SRT_EphemTab ); - testcase( pDest->eDest==SRT_Fifo ); - testcase( pDest->eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); -#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG) - /* A destination of SRT_Table and a non-zero iSDParm2 parameter means - ** that this is an "UPDATE ... FROM" on a virtual table or view. In this - ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC. - ** This does not affect operation in any way - it just allows MakeRecord - ** to process OPFLAG_NOCHANGE values without an assert() failing. */ - if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){ - sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC); - } -#endif -#ifndef SQLITE_OMIT_CTE - if( pDest->eDest==SRT_DistFifo ){ - /* If the destination is DistFifo, then cursor (iParm+1) is open - ** on an ephemeral index that is used to enforce uniqueness on the - ** total result. At this point, we are processing the setup portion - ** of the recursive CTE using the merge algorithm, so the results are - ** guaranteed to be unique anyhow. But we still need to populate the - ** (iParm+1) cursor for use by the subsequent recursive phase. - */ - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1, - pIn->iSdst, pIn->nSdst); - } -#endif - sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); - sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); + sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); + sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); sqlite3ReleaseTempReg(pParse, r1); break; } - /* If any row exist in the result set, record that fact and abort. - */ - case SRT_Exists: { - sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); - /* The LIMIT clause will terminate the loop for us */ - break; - } - #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)". */ @@ -151135,51 +150213,9 @@ static int generateOutputSubroutine( break; } -#ifndef SQLITE_OMIT_CTE - /* Write the results into a priority queue that is order according to - ** pDest->pOrderBy (in pSO). pDest->iSDParm (in iParm) is the cursor for an - ** index with pSO->nExpr+2 columns. Build a key using pSO for the first - ** pSO->nExpr columns, then make sure all keys are unique by adding a - ** final OP_Sequence column. The last column is the record as a blob. - */ - case SRT_DistQueue: - case SRT_Queue: { - int nKey; - int r1, r2, r3, ii; - ExprList *pSO; - int iParm = pDest->iSDParm; - pSO = pDest->pOrderBy; - assert( pSO ); - nKey = pSO->nExpr; - r1 = sqlite3GetTempReg(pParse); - r2 = sqlite3GetTempRange(pParse, nKey+2); - r3 = r2+nKey+1; - - sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r3); - if( pDest->eDest==SRT_DistQueue ){ - sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3); - } - for(ii=0; iiiSdst + pSO->a[ii].u.x.iOrderByCol - 1, - r2+ii); - } - sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); - sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); - sqlite3ReleaseTempReg(pParse, r1); - sqlite3ReleaseTempRange(pParse, r2, nKey+2); - break; - } -#endif /* SQLITE_OMIT_CTE */ - - /* Ignore the output */ - case SRT_Discard: { - break; - } - /* If none of the above, then the result destination must be - ** SRT_Output. + ** SRT_Output. This routine is never called with any other + ** destination other than the ones handled above or SRT_Output. ** ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to @@ -151207,9 +150243,8 @@ static int generateOutputSubroutine( } /* -** Generate code for a compound SELECT statement using a merge -** algorithm. The compound must have an ORDER BY clause for this -** to work. +** Alternative compound select code generator for cases when there +** is an ORDER BY clause. ** ** We assume a query of the following form: ** @@ -151226,7 +150261,7 @@ static int generateOutputSubroutine( ** ** outB: Move the output of the selectB coroutine into the output ** of the compound query. (Only generated for UNION and -** UNION ALL. EXCEPT and INTERSECT never output a row that +** UNION ALL. EXCEPT and INSERTSECT never output a row that ** appears only in B.) ** ** AltB: Called when there is data from both coroutines and Au.x.iOrderByCol==i ) break; } if( j==nOrderBy ){ - Expr *pNew = sqlite3ExprInt32(db, i); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return SQLITE_NOMEM_BKPT; + pNew->flags |= EP_IntValue; + pNew->u.iValue = i; p->pOrderBy = pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i; } @@ -151372,29 +150411,26 @@ static int multiSelectByMerge( } /* Compute the comparison permutation and keyinfo that is used with - ** the permutation to determine if the next row of results comes - ** from selectA or selectB. Also add literal collations to the - ** ORDER BY clause terms so that when selectA and selectB are - ** evaluated, they use the correct collation. + ** the permutation used to determine if the next + ** row of results comes from selectA or selectB. Also add explicit + ** collations to the ORDER BY clause terms so that when the subqueries + ** to the right and the left are evaluated, they use the correct + ** collation. */ aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1)); if( aPermute ){ struct ExprList_item *pItem; - int bKeep = 0; aPermute[0] = nOrderBy; for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ assert( pItem!=0 ); assert( pItem->u.x.iOrderByCol>0 ); assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; - if( aPermute[i]!=(u32)i-1 ) bKeep = 1; - } - if( bKeep==0 ){ - sqlite3DbFreeNN(db, aPermute); - aPermute = 0; } + pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); + }else{ + pKeyMerge = 0; } - pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1); /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the @@ -151473,7 +150509,7 @@ static int multiSelectByMerge( */ addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); - VdbeComment((v, "SUBR: next-A")); + VdbeComment((v, "left SELECT")); pPrior->iLimit = regLimitA; ExplainQueryPlan((pParse, 1, "LEFT")); sqlite3Select(pParse, pPrior, &destA); @@ -151485,7 +150521,7 @@ static int multiSelectByMerge( */ addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); - VdbeComment((v, "SUBR: next-B")); + VdbeComment((v, "right SELECT")); savedLimit = p->iLimit; savedOffset = p->iOffset; p->iLimit = regLimitB; @@ -151499,7 +150535,7 @@ static int multiSelectByMerge( /* Generate a subroutine that outputs the current row of the A ** select as the next output row of the compound select. */ - VdbeNoopComment((v, "SUBR: out-A")); + VdbeNoopComment((v, "Output routine for A")); addrOutA = generateOutputSubroutine(pParse, p, &destA, pDest, regOutA, regPrev, pKeyDup, labelEnd); @@ -151508,7 +150544,7 @@ static int multiSelectByMerge( ** select as the next output row of the compound select. */ if( op==TK_ALL || op==TK_UNION ){ - VdbeNoopComment((v, "SUBR: out-B")); + VdbeNoopComment((v, "Output routine for B")); addrOutB = generateOutputSubroutine(pParse, p, &destB, pDest, regOutB, regPrev, pKeyDup, labelEnd); @@ -151521,12 +150557,10 @@ static int multiSelectByMerge( if( op==TK_EXCEPT || op==TK_INTERSECT ){ addrEofA_noB = addrEofA = labelEnd; }else{ - VdbeNoopComment((v, "SUBR: eof-A")); + VdbeNoopComment((v, "eof-A subroutine")); addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - VdbeComment((v, "out-B")); addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); VdbeCoverage(v); - VdbeComment((v, "next-B")); sqlite3VdbeGoto(v, addrEofA); p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); } @@ -151538,20 +150572,17 @@ static int multiSelectByMerge( addrEofB = addrEofA; if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow; }else{ - VdbeNoopComment((v, "SUBR: eof-B")); + VdbeNoopComment((v, "eof-B subroutine")); addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); - VdbeComment((v, "out-A")); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); - VdbeComment((v, "next-A")); sqlite3VdbeGoto(v, addrEofB); } /* Generate code to handle the case of AB */ + VdbeNoopComment((v, "A-gt-B subroutine")); addrAgtB = sqlite3VdbeCurrentAddr(v); if( op==TK_ALL || op==TK_UNION ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); - VdbeComment((v, "out-B")); - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - VdbeComment((v, "next-B")); - sqlite3VdbeGoto(v, labelCmpr); - }else{ - addrAgtB++; /* Just do next-B. Might as well use the next-B call - ** in the next code block */ } + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); + sqlite3VdbeGoto(v, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); - VdbeComment((v, "next-A")); - /* v--- Also the A>B case for EXCEPT and INTERSECT */ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - VdbeComment((v, "next-B")); /* Implement the main merge loop */ - if( aPermute!=0 ){ - sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); - } sqlite3VdbeResolveLabel(v, labelCmpr); + sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO); - if( aPermute!=0 ){ - sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); - } - sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); - VdbeCoverageIf(v, op==TK_ALL); - VdbeCoverageIf(v, op==TK_UNION); - VdbeCoverageIf(v, op==TK_EXCEPT); - VdbeCoverageIf(v, op==TK_INTERSECT); + sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); + sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverage(v); /* Jump to the this point in order to terminate the query. */ @@ -152520,7 +151539,7 @@ static int flattenSubquery( } pSubitem->fg.jointype |= jointype; - /* Begin substituting subquery result set expressions for + /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. ** ** Example: @@ -152532,7 +151551,7 @@ 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". */ - if( pSub->pOrderBy ){ + if( pSub->pOrderBy && (pParent->selFlags & SF_NoopOrderBy)==0 ){ /* At this point, any non-zero iOrderByCol values indicate that the ** ORDER BY column expression is identical to the iOrderByCol'th ** expression returned by SELECT statement pSub. Since these values @@ -152540,9 +151559,9 @@ static int flattenSubquery( ** zero them before transferring the ORDER BY clause. ** ** Not doing this may cause an error if a subsequent call to this - ** function attempts to flatten a compound sub-query into pParent. - ** See ticket [d11a6e908f]. - */ + ** function attempts to flatten a compound sub-query into pParent + ** (the only way this can happen is if the compound sub-query is + ** currently part of pSub->pSrc). See ticket [d11a6e908f]. */ ExprList *pOrderBy = pSub->pOrderBy; for(i=0; inExpr; i++){ pOrderBy->a[i].u.x.iOrderByCol = 0; @@ -153160,16 +152179,6 @@ static int pushDownWhereTerms( x.pEList = pSubq->pEList; x.pCList = findLeftmostExprlist(pSubq); pNew = substExpr(&x, pNew); - assert( pNew!=0 || pParse->nErr!=0 ); - if( pParse->nErr==0 && pNew->op==TK_IN && ExprUseXSelect(pNew) ){ - assert( pNew->x.pSelect!=0 ); - pNew->x.pSelect->selFlags |= SF_ClonedRhsIn; - assert( pWhere!=0 ); - assert( pWhere->op==TK_IN ); - assert( ExprUseXSelect(pWhere) ); - assert( pWhere->x.pSelect!=0 ); - pWhere->x.pSelect->selFlags |= SF_ClonedRhsIn; - } #ifndef SQLITE_OMIT_WINDOWFUNC if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){ /* Restriction 6c has prevented push-down in this case */ @@ -153404,14 +152413,14 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){ ** SELECT * FROM (SELECT ... FROM t1 EXCEPT SELECT ... FROM t2) ** ORDER BY ... COLLATE ... ** -** This transformation is necessary because the multiSelectByMerge() routine +** This transformation is necessary because the multiSelectOrderBy() routine ** above that generates the code for a compound SELECT with an ORDER BY clause ** uses a merge algorithm that requires the same collating sequence on the ** result columns as on the ORDER BY clause. See ticket ** http://sqlite.org/src/info/6709574d2a ** ** This transformation is only needed for EXCEPT, INTERSECT, and UNION. -** The UNION ALL operator works fine with multiSelectByMerge() even when +** The UNION ALL operator works fine with multiSelectOrderBy() even when ** there are COLLATE terms in the ORDER BY. */ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ @@ -153957,7 +152966,7 @@ static int selectExpander(Walker *pWalker, Select *p){ } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( ALWAYS(IsVirtual(pTab)) - && (pFrom->fg.fromDDL || (pParse->prepFlags & SQLITE_PREPARE_FROM_DDL)) + && pFrom->fg.fromDDL && ALWAYS(pTab->u.vtab.p!=0) && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) ){ @@ -154910,7 +153919,7 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ && pExpr->pAggInfo==0 ){ sqlite3 *db = pWalker->pParse->db; - Expr *pNew = sqlite3ExprInt32(db, 1); + Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1"); if( pNew ){ Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); @@ -155261,6 +154270,7 @@ static SQLITE_NOINLINE void existsToJoin( ExprSetProperty(pWhere, EP_IntValue); assert( p->pWhere!=0 ); pSub->pSrc->a[0].fg.fromExists = 1; + pSub->pSrc->a[0].fg.jointype |= JT_CROSS; p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc); if( pSubWhere ){ p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere); @@ -155288,7 +154298,6 @@ typedef struct CheckOnCtx CheckOnCtx; struct CheckOnCtx { SrcList *pSrc; /* SrcList for this context */ int iJoin; /* Cursor numbers must be =< than this */ - int bFuncArg; /* True for table-function arg */ CheckOnCtx *pParent; /* Parent context */ }; @@ -155340,9 +154349,7 @@ static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){ if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){ if( pCtx->iJoin && iTab>pCtx->iJoin ){ sqlite3ErrorMsg(pWalker->pParse, - "%s references tables to its right", - (pCtx->bFuncArg ? "table-function argument" : "ON clause") - ); + "ON clause references tables to its right"); return WRC_Abort; } break; @@ -155380,7 +154387,6 @@ static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){ SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){ Walker w; CheckOnCtx sCtx; - int ii; assert( pSelect->selFlags & SF_OnToWhere ); assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 ); memset(&w, 0, sizeof(w)); @@ -155390,46 +154396,8 @@ SQLITE_PRIVATE void sqlite3SelectCheckOnClauses(Parse *pParse, Select *pSelect){ w.u.pCheckOnCtx = &sCtx; memset(&sCtx, 0, sizeof(sCtx)); sCtx.pSrc = pSelect->pSrc; - sqlite3WalkExpr(&w, pSelect->pWhere); + sqlite3WalkExprNN(&w, pSelect->pWhere); pSelect->selFlags &= ~SF_OnToWhere; - - /* Check for any table-function args that are attached to virtual tables - ** on the RHS of an outer join. They are subject to the same constraints - ** as ON clauses. */ - sCtx.bFuncArg = 1; - for(ii=0; iipSrc->nSrc; ii++){ - SrcItem *pItem = &pSelect->pSrc->a[ii]; - if( pItem->fg.isTabFunc - && (pItem->fg.jointype & JT_OUTER) - ){ - sCtx.iJoin = pItem->iCursor; - sqlite3WalkExprList(&w, pItem->u1.pFuncArg); - } - } -} - -/* -** If p2 exists and p1 and p2 have the same number of terms, then change -** every term of p1 to have the same sort order as p2 and return true. -** -** If p2 is NULL or p1 and p2 are different lengths, then make no changes -** and return false. -** -** p1 must be non-NULL. -*/ -static int sqlite3CopySortOrder(ExprList *p1, ExprList *p2){ - assert( p1 ); - if( p2 && p1->nExpr==p2->nExpr ){ - int ii; - for(ii=0; iinExpr; ii++){ - u8 sortFlags; - sortFlags = p2->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; - p1->a[ii].fg.sortFlags = sortFlags; - } - return 1; - }else{ - return 0; - } } /* @@ -155527,7 +154495,8 @@ SQLITE_PRIVATE int sqlite3Select( assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue ); assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue ); if( IgnorableDistinct(pDest) ){ - assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Discard || + assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || + pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard || pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo ); /* All of these destinations are also able to ignore the ORDER BY clause */ if( p->pOrderBy ){ @@ -155543,6 +154512,7 @@ SQLITE_PRIVATE int sqlite3Select( p->pOrderBy = 0; } p->selFlags &= ~(u32)SF_Distinct; + p->selFlags |= SF_NoopOrderBy; } sqlite3SelectPrep(pParse, p, 0); if( pParse->nErr ){ @@ -156070,8 +155040,7 @@ SQLITE_PRIVATE int sqlite3Select( ** BY and DISTINCT, and an index or separate temp-table for the other. */ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct - && sqlite3CopySortOrder(pEList, sSort.pOrderBy) - && sqlite3ExprListCompare(pEList, sSort.pOrderBy, -1)==0 + && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 && OptimizationEnabled(db, SQLITE_GroupByOrder) #ifndef SQLITE_OMIT_WINDOWFUNC && p->pWin==0 @@ -156285,10 +155254,21 @@ SQLITE_PRIVATE int sqlite3Select( ** but not actually sorted. Either way, record the fact that the ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp ** variable. */ - if( sqlite3CopySortOrder(pGroupBy, sSort.pOrderBy) - && sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 - ){ - orderByGrp = 1; + if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){ + int ii; + /* The GROUP BY processing doesn't care whether rows are delivered in + ** ASC or DESC order - only that each group is returned contiguously. + ** So set the ASC/DESC flags in the GROUP BY to match those in the + ** ORDER BY to maximize the chances of rows being delivered in an + ** order that makes the ORDER BY redundant. */ + for(ii=0; iinExpr; ii++){ + u8 sortFlags; + sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; + pGroupBy->a[ii].fg.sortFlags = sortFlags; + } + if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ + orderByGrp = 1; + } } }else{ assert( 0==sqlite3LogEst(1) ); @@ -157098,7 +156078,7 @@ SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerS sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); sqlite3UpsertDelete(db, pTmp->pUpsert); - sqlite3SrcListDelete(db, pTmp->pSrc); + sqlite3SrcListDelete(db, pTmp->pFrom); sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); @@ -157287,16 +156267,11 @@ SQLITE_PRIVATE void sqlite3BeginTrigger( } } - /* NB: The SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES compile-time option is - ** experimental and unsupported. Do not use it unless understand the - ** implications and you cannot get by without this capability. */ -#if !defined(SQLITE_ALLOW_TRIGGERS_ON_SYSTEM_TABLES) /* Experimental */ /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); goto trigger_cleanup; } -#endif /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. @@ -157408,7 +156383,6 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); - assert( iDb>=00 && iDbnDb ); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; @@ -157443,12 +156417,12 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( if( sqlite3ReadOnlyShadowTables(db) ){ TriggerStep *pStep; for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){ - if( pStep->pSrc!=0 - && sqlite3ShadowTableName(db, pStep->pSrc->a[0].zName) + if( pStep->zTarget!=0 + && sqlite3ShadowTableName(db, pStep->zTarget) ){ sqlite3ErrorMsg(pParse, "trigger \"%s\" may not write to shadow table \"%s\"", - pTrig->zName, pStep->pSrc->a[0].zName); + pTrig->zName, pStep->zTarget); goto triggerfinish_cleanup; } } @@ -157539,39 +156513,26 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep( static TriggerStep *triggerStepAllocate( Parse *pParse, /* Parser context */ u8 op, /* Trigger opcode */ - SrcList *pTabList, /* Target table */ + Token *pName, /* The target name */ const char *zStart, /* Start of SQL text */ const char *zEnd /* End of SQL text */ ){ - Trigger *pNew = pParse->pNewTrigger; sqlite3 *db = pParse->db; - TriggerStep *pTriggerStep = 0; + TriggerStep *pTriggerStep; - if( pParse->nErr==0 ){ - if( pNew - && pNew->pSchema!=db->aDb[1].pSchema - && pTabList->a[0].u4.zDatabase - ){ - sqlite3ErrorMsg(pParse, - "qualified table names are not allowed on INSERT, UPDATE, and DELETE " - "statements within triggers"); - }else{ - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); - if( pTriggerStep ){ - pTriggerStep->pSrc = sqlite3SrcListDup(db, pTabList, EXPRDUP_REDUCE); - pTriggerStep->op = op; - pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); - if( pTriggerStep->pSrc && IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, - pTriggerStep->pSrc->a[0].zName, - pTabList->a[0].zName - ); - } - } + if( pParse->nErr ) return 0; + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); + if( pTriggerStep ){ + char *z = (char*)&pTriggerStep[1]; + memcpy(z, pName->z, pName->n); + sqlite3Dequote(z); + pTriggerStep->zTarget = z; + pTriggerStep->op = op; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); + if( IN_RENAME_OBJECT ){ + sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); } } - - sqlite3SrcListDelete(db, pTabList); return pTriggerStep; } @@ -157584,7 +156545,7 @@ static TriggerStep *triggerStepAllocate( */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( Parse *pParse, /* Parser */ - SrcList *pTabList, /* Table to INSERT into */ + Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ Select *pSelect, /* A SELECT statement that supplies values */ u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ @@ -157597,7 +156558,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( assert(pSelect != 0 || db->mallocFailed); - pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTabList, zStart, zEnd); + pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); if( pTriggerStep ){ if( IN_RENAME_OBJECT ){ pTriggerStep->pSelect = pSelect; @@ -157629,7 +156590,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( Parse *pParse, /* Parser */ - SrcList *pTabList, /* Name of the table to be updated */ + Token *pTableName, /* Name of the table to be updated */ SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ @@ -157640,36 +156601,21 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTabList, zStart, zEnd); + pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); if( pTriggerStep ){ - SrcList *pFromDup = 0; if( IN_RENAME_OBJECT ){ pTriggerStep->pExprList = pEList; pTriggerStep->pWhere = pWhere; - pFromDup = pFrom; + pTriggerStep->pFrom = pFrom; pEList = 0; pWhere = 0; pFrom = 0; }else{ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); - pFromDup = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE); + pTriggerStep->pFrom = sqlite3SrcListDup(db, pFrom, EXPRDUP_REDUCE); } pTriggerStep->orconf = orconf; - - if( pFromDup && !IN_RENAME_OBJECT){ - Select *pSub; - Token as = {0, 0}; - pSub = sqlite3SelectNew(pParse, 0, pFromDup, 0,0,0,0, SF_NestedFrom, 0); - pFromDup = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &as, pSub ,0); - } - if( pFromDup && pTriggerStep->pSrc ){ - pTriggerStep->pSrc = sqlite3SrcListAppendList( - pParse, pTriggerStep->pSrc, pFromDup - ); - }else{ - sqlite3SrcListDelete(db, pFromDup); - } } sqlite3ExprListDelete(db, pEList); sqlite3ExprDelete(db, pWhere); @@ -157684,7 +156630,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( */ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( Parse *pParse, /* Parser */ - SrcList *pTabList, /* The table from which rows are deleted */ + Token *pTableName, /* The table from which rows are deleted */ Expr *pWhere, /* The WHERE clause */ const char *zStart, /* Start of SQL text */ const char *zEnd /* End of SQL text */ @@ -157692,7 +156638,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep( sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTabList, zStart, zEnd); + pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); if( pTriggerStep ){ if( IN_RENAME_OBJECT ){ pTriggerStep->pWhere = pWhere; @@ -157892,7 +156838,6 @@ static SQLITE_NOINLINE Trigger *triggersReallyExist( p = pList; if( (pParse->db->flags & SQLITE_EnableTrigger)==0 && pTab->pTrigger!=0 - && sqlite3SchemaToIndex(pParse->db, pTab->pTrigger->pSchema)!=1 ){ /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that ** only TEMP triggers are allowed. Truncate the pList so that it @@ -157955,6 +156900,52 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist( return triggersReallyExist(pParse,pTab,op,pChanges,pMask); } +/* +** Convert the pStep->zTarget string into a SrcList and return a pointer +** to that SrcList. +** +** This routine adds a specific database name, if needed, to the target when +** forming the SrcList. This prevents a trigger in one database from +** referring to a target in another database. An exception is when the +** trigger is in TEMP in which case it can refer to any other database it +** wants. +*/ +SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc( + Parse *pParse, /* The parsing context */ + TriggerStep *pStep /* The trigger containing the target token */ +){ + sqlite3 *db = pParse->db; + SrcList *pSrc; /* SrcList to be returned */ + char *zName = sqlite3DbStrDup(db, pStep->zTarget); + pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); + assert( pSrc==0 || pSrc->nSrc==1 ); + assert( zName || pSrc==0 ); + if( pSrc ){ + Schema *pSchema = pStep->pTrig->pSchema; + pSrc->a[0].zName = zName; + if( pSchema!=db->aDb[1].pSchema ){ + assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 ); + pSrc->a[0].u4.pSchema = pSchema; + pSrc->a[0].fg.fixedSchema = 1; + } + if( pStep->pFrom ){ + SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0); + if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){ + Select *pSubquery; + Token as; + pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0); + as.n = 0; + as.z = 0; + pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); + } + pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup); + } + }else{ + sqlite3DbFree(db, zName); + } + return pSrc; +} + /* ** Return true if the pExpr term from the RETURNING clause argument ** list is of the form "*". Raise an error if the terms if of the @@ -158220,7 +157211,7 @@ static int codeTriggerProgram( switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, - sqlite3SrcListDup(db, pStep->pSrc, 0), + sqlite3TriggerStepSrc(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), pParse->eOrconf, 0, 0, 0 @@ -158230,7 +157221,7 @@ static int codeTriggerProgram( } case TK_INSERT: { sqlite3Insert(pParse, - sqlite3SrcListDup(db, pStep->pSrc, 0), + sqlite3TriggerStepSrc(pParse, pStep), sqlite3SelectDup(db, pStep->pSelect, 0), sqlite3IdListDup(db, pStep->pIdList), pParse->eOrconf, @@ -158241,7 +157232,7 @@ static int codeTriggerProgram( } case TK_DELETE: { sqlite3DeleteFrom(pParse, - sqlite3SrcListDup(db, pStep->pSrc, 0), + sqlite3TriggerStepSrc(pParse, pStep), sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0 ); sqlite3VdbeAddOp0(v, OP_ResetCount); @@ -160563,11 +159554,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( pDb = &db->aDb[nDb]; assert( strcmp(pDb->zDbSName,zDbVacuum)==0 ); pTemp = pDb->pBt; - nRes = sqlite3BtreeGetRequestedReserve(pMain); if( pOut ){ sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp)); i64 sz = 0; - const char *zFilename; if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){ rc = SQLITE_ERROR; sqlite3SetString(pzErrMsg, db, "output file already exists"); @@ -160579,16 +159568,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( ** they are for the database being vacuumed, except that PAGER_CACHESPILL ** is always set. */ pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK); - - /* If the VACUUM INTO target file is a URI filename and if the - ** "reserve=N" query parameter is present, reset the reserve to the - ** amount specified, if the amount is within range */ - zFilename = sqlite3BtreeGetFilename(pTemp); - if( ALWAYS(zFilename) ){ - int nNew = (int)sqlite3_uri_int64(zFilename, "reserve", nRes); - if( nNew>=0 && nNew<=255 ) nRes = nNew; - } } + nRes = sqlite3BtreeGetRequestedReserve(pMain); sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size); sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0)); @@ -164393,7 +163374,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){ int iTab = pParse->nTab++; int iCache = ++pParse->nMem; - sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab, 0); + sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab); sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache); }else{ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); @@ -165712,6 +164693,15 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); } } + if( pLevel->iIdxCur ){ + /* pSubWhere may contain expressions that read from an index on the + ** table on the RHS of the right join. All such expressions first test + ** if the index is pointing at a NULL row, and if so, read from the + ** table cursor instead. So ensure that the index cursor really is + ** pointing at a NULL row here, so that no values are read from it during + ** the scan of the RHS of the RIGHT join below. */ + sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); + } pFrom = &uSrc.sSrc; pFrom->nSrc = 1; pFrom->nAlloc = 1; @@ -166052,14 +165042,13 @@ static int isLikeOrGlob( ){ int isNum; double rDummy; - assert( zNew[iTo]==0 ); - isNum = sqlite3AtoF(zNew, &rDummy); + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); if( isNum<=0 ){ if( iTo==1 && zNew[0]=='-' ){ isNum = +1; }else{ zNew[iTo-1]++; - isNum = sqlite3AtoF(zNew, &rDummy); + isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8); zNew[iTo-1]--; } } @@ -166102,34 +165091,6 @@ static int isLikeOrGlob( } #endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */ -/* -** If pExpr is one of "like", "glob", "match", or "regexp", then -** return the corresponding SQLITE_INDEX_CONSTRAINT_xxxx value. -** If not, return 0. -** -** pExpr is guaranteed to be a TK_FUNCTION. -*/ -SQLITE_PRIVATE int sqlite3ExprIsLikeOperator(const Expr *pExpr){ - static const struct { - const char *zOp; - unsigned char eOp; - } aOp[] = { - { "match", SQLITE_INDEX_CONSTRAINT_MATCH }, - { "glob", SQLITE_INDEX_CONSTRAINT_GLOB }, - { "like", SQLITE_INDEX_CONSTRAINT_LIKE }, - { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP } - }; - int i; - assert( pExpr->op==TK_FUNCTION ); - assert( !ExprHasProperty(pExpr, EP_IntValue) ); - for(i=0; iu.zToken, aOp[i].zOp)==0 ){ - return aOp[i].eOp; - } - } - return 0; -} - #ifndef SQLITE_OMIT_VIRTUALTABLE /* @@ -166166,6 +165127,15 @@ static int isAuxiliaryVtabOperator( 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; @@ -166185,11 +165155,16 @@ static int isAuxiliaryVtabOperator( */ pCol = pList->a[1].pExpr; assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) ); - if( ExprIsVtab(pCol) && (i = sqlite3ExprIsLikeOperator(pExpr))!=0 ){ - *peOp2 = i; - *ppRight = pList->a[0].pExpr; - *ppLeft = pCol; - return 1; + if( ExprIsVtab(pCol) ){ + for(i=0; iu.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; + *ppRight = pList->a[0].pExpr; + *ppLeft = pCol; + return 1; + } + } } /* We can also match against the first column of overloaded @@ -166323,22 +165298,16 @@ static void whereCombineDisjuncts( Expr *pNew; /* New virtual expression */ int op; /* Operator for the combined expression */ int idxNew; /* Index in pWC of the next virtual term */ - Expr *pA, *pB; /* Expressions associated with pOne and pTwo */ if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return; if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; - pA = pOne->pExpr; - pB = pTwo->pExpr; - assert( pA->pLeft!=0 && pA->pRight!=0 ); - assert( pB->pLeft!=0 && pB->pRight!=0 ); - if( sqlite3ExprCompare(0,pA->pLeft, pB->pLeft, -1) ) return; - if( sqlite3ExprCompare(0,pA->pRight, pB->pRight,-1) ) return; - if( ExprHasProperty(pA,EP_Commuted)!=ExprHasProperty(pB,EP_Commuted) ){ - return; - } + assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); + assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); + if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; + if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return; /* If we reach this point, it means the two subterms can be combined */ if( (eOp & (eOp-1))!=0 ){ if( eOp & (WO_LT|WO_LE) ){ @@ -166349,7 +165318,7 @@ static void whereCombineDisjuncts( } } db = pWC->pWInfo->pParse->db; - pNew = sqlite3ExprDup(db, pA, 0); + pNew = sqlite3ExprDup(db, pOne->pExpr, 0); if( pNew==0 ) return; for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op; @@ -167389,11 +166358,13 @@ static void whereAddLimitExpr( int iVal = 0; if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){ - Expr *pVal = sqlite3ExprInt32(db, iVal); + Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0); if( pVal==0 ) return; + ExprSetProperty(pVal, EP_IntValue); + pVal->u.iValue = iVal; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); }else{ - Expr *pVal = sqlite3ExprAlloc(db, TK_REGISTER, 0, 0); + Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0); if( pVal==0 ) return; pVal->iTable = iReg; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); @@ -169220,14 +168191,11 @@ static sqlite3_index_info *allocateIndexInfo( break; } if( i==n ){ - int bSortByGroup = (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0; nOrderBy = n; if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) && !pSrc->fg.rowidUsed ){ - eDistinct = 2 + bSortByGroup; + eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ - eDistinct = 1 - bSortByGroup; - }else if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ - eDistinct = 3; + eDistinct = 1; } } } @@ -170638,67 +169606,6 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ return rc; } -/* -** Callback for estLikePatternLength(). -** -** If this node is a string literal that is longer pWalker->sz, then set -** pWalker->sz to the byte length of that string literal. -** -** pWalker->eCode indicates how to count characters: -** -** eCode==0 Count as a GLOB pattern -** eCode==1 Count as a LIKE pattern -*/ -static int exprNodePatternLengthEst(Walker *pWalker, Expr *pExpr){ - if( pExpr->op==TK_STRING ){ - int sz = 0; /* Pattern size in bytes */ - u8 *z = (u8*)pExpr->u.zToken; /* The pattern */ - u8 c; /* Next character of the pattern */ - u8 c1, c2, c3; /* Wildcards */ - if( pWalker->eCode ){ - c1 = '%'; - c2 = '_'; - c3 = 0; - }else{ - c1 = '*'; - c2 = '?'; - c3 = '['; - } - while( (c = *(z++))!=0 ){ - if( c==c3 ){ - if( *z ) z++; - while( *z && *z!=']' ) z++; - }else if( c!=c1 && c!=c2 ){ - sz++; - } - } - if( sz>pWalker->u.sz ) pWalker->u.sz = sz; - } - return WRC_Continue; -} - -/* -** Return the length of the longest string literal in the given -** expression. -** -** eCode indicates how to count characters: -** -** eCode==0 Count as a GLOB pattern -** eCode==1 Count as a LIKE pattern -*/ -static int estLikePatternLength(Expr *p, u16 eCode){ - Walker w; - w.u.sz = 0; - w.eCode = eCode; - w.xExprCallback = exprNodePatternLengthEst; - w.xSelectCallback = sqlite3SelectWalkFail; -#ifdef SQLITE_DEBUG - w.xSelectCallback2 = sqlite3SelectWalkAssert2; -#endif - sqlite3WalkExpr(&w, p); - return w.u.sz; -} - /* ** Adjust the WhereLoop.nOut value downward to account for terms of the ** WHERE clause that reference the loop but which are not used by an @@ -170727,13 +169634,6 @@ static int estLikePatternLength(Expr *p, u16 eCode){ ** "x" column is boolean or else -1 or 0 or 1 is a common default value ** on the "x" column and so in that case only cap the output row estimate ** at 1/2 instead of 1/4. -** -** Heuristic 3: If there is a LIKE or GLOB (or REGEXP or MATCH) operator -** with a large constant pattern, then reduce the size of the search -** space according to the length of the pattern, under the theory that -** longer patterns are less likely to match. This heuristic was added -** to give better output-row count estimates when preparing queries for -** the Join-Order Benchmarks. See forum thread 2026-01-30T09:57:54z */ static void whereLoopOutputAdjust( WhereClause *pWC, /* The WHERE clause */ @@ -170783,14 +169683,13 @@ static void whereLoopOutputAdjust( }else{ /* In the absence of explicit truth probabilities, use heuristics to ** guess a reasonable truth probability. */ - Expr *pOpExpr = pTerm->pExpr; pLoop->nOut--; if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */ ){ - Expr *pRight = pOpExpr->pRight; + Expr *pRight = pTerm->pExpr->pRight; int k = 0; - testcase( pOpExpr->op==TK_IS ); + testcase( pTerm->pExpr->op==TK_IS ); if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){ k = 10; }else{ @@ -170800,23 +169699,6 @@ static void whereLoopOutputAdjust( pTerm->wtFlags |= TERM_HEURTRUTH; iReduce = k; } - }else - if( ExprHasProperty(pOpExpr, EP_InfixFunc) - && pOpExpr->op==TK_FUNCTION - ){ - int eOp; - assert( ExprUseXList(pOpExpr) ); - assert( pOpExpr->x.pList->nExpr>=2 ); - eOp = sqlite3ExprIsLikeOperator(pOpExpr); - if( ALWAYS(eOp>0) ){ - int szPattern; - Expr *pRHS = pOpExpr->x.pList->a[0].pExpr; - eOp = eOp==SQLITE_INDEX_CONSTRAINT_LIKE; - szPattern = estLikePatternLength(pRHS, eOp); - if( szPattern>0 ){ - pLoop->nOut -= szPattern*2; - } - } } } } @@ -170888,7 +169770,7 @@ static int whereRangeVectorLen( idxaff = sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); if( aff!=idxaff ) break; - pColl = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr); + pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); if( pColl==0 ) break; if( sqlite3StrICmp(pColl->zName, pIdx->azColl[i+nEq]) ) break; } @@ -171277,7 +170159,6 @@ static int whereLoopAddBtreeIndex( pNew->rRun += nInMul + nIn; pNew->nOut += nInMul + nIn; whereLoopOutputAdjust(pBuilder->pWC, pNew, rSize); - if( pSrc->fg.fromExists ) pNew->nOut = 0; rc = whereLoopInsert(pBuilder, pNew); if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ @@ -171874,8 +170755,6 @@ static int whereLoopAddBtree( if( pSrc->fg.isSubquery ){ if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE; pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy; - }else if( pSrc->fg.fromExists ){ - pNew->nOut = 0; } rc = whereLoopInsert(pBuilder, pNew); pNew->nOut = rSize; @@ -171978,7 +170857,6 @@ static int whereLoopAddBtree( ** positioned to the correct row during the right-join no-match ** loop. */ }else{ - if( pSrc->fg.fromExists ) pNew->nOut = 0; rc = whereLoopInsert(pBuilder, pNew); } pNew->nOut = rSize; @@ -172641,7 +171519,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ sqlite3 *db = pWInfo->pParse->db; int rc = SQLITE_OK; int bFirstPastRJ = 0; - int hasRightCrossJoin = 0; + int hasRightJoin = 0; WhereLoop *pNew; @@ -172668,34 +171546,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ ** prevents the right operand of a RIGHT JOIN from being swapped with ** other elements even further to the right. ** - ** The hasRightCrossJoin flag prevent FROM-clause terms from moving - ** from the right side of a LEFT JOIN or CROSS JOIN over to the - ** left side of that same join. This is a required restriction in - ** the case of LEFT JOIN - an incorrect answer may results if it is - ** not enforced. This restriction is not required for CROSS JOIN. - ** It is provided merely as a means of controlling join order, under - ** the theory that no real-world queries that care about performance - ** actually use the CROSS JOIN syntax. + ** The JT_LTORJ case and the hasRightJoin flag work together to + ** prevent FROM-clause terms from moving from the right side of + ** a LEFT JOIN over to the left side of that join if the LEFT JOIN + ** is itself on the left side of a RIGHT JOIN. */ - if( pItem->fg.jointype & (JT_LTORJ|JT_CROSS) ){ - testcase( pItem->fg.jointype & JT_LTORJ ); - testcase( pItem->fg.jointype & JT_CROSS ); - hasRightCrossJoin = 1; - } + if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1; mPrereq |= mPrior; bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0; - }else if( pItem->fg.fromExists ){ - /* joins that result from the EXISTS-to-JOIN optimization should not - ** be moved to the left of any of their dependencies */ - WhereClause *pWC = &pWInfo->sWC; - WhereTerm *pTerm; - int i; - for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){ - if( (pNew->maskSelf & pTerm->prereqAll)!=0 ){ - mPrereq |= (pTerm->prereqAll & (pNew->maskSelf-1)); - } - } - }else if( !hasRightCrossJoin ){ + }else if( !hasRightJoin ){ mPrereq = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -172918,7 +171777,9 @@ static i8 wherePathSatisfiesOrderBy( pLoop = pLast; } if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered && pWInfo->pOrderBy==pOrderBy ){ + if( pLoop->u.vtab.isOrdered + && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) + ){ obSat = obDone; }else{ /* No further ORDER BY terms may be matched. So this call should @@ -173294,21 +172155,12 @@ static LogEst whereSortingCost( ** 12 otherwise ** ** For the purposes of this heuristic, a star-query is defined as a query -** with a central "fact" table that is joined against multiple -** "dimension" tables, subject to the following constraints: -** -** (aa) Only a five-way or larger join is considered for this -** optimization. If there are fewer than four terms in the FROM -** clause, this heuristic does not apply. -** -** (bb) The join between the fact table and the dimension tables must -** be an INNER join. CROSS and OUTER JOINs do not qualify. -** -** (cc) A table must have 3 or more dimension tables in order to be -** considered a fact table. (Was 4 prior to 2026-02-10.) -** -** (dd) A table that is a self-join cannot be a dimension table. -** Dimension tables are joined against fact tables. +** with a large central table that is joined using an INNER JOIN, +** not CROSS or OUTER JOINs, against four or more smaller tables. +** The central table is called the "fact" table. The smaller tables +** that get joined are "dimension tables". Also, any table that is +** self-joined cannot be a dimension table; we assume that dimension +** tables may only be joined against fact tables. ** ** SIDE EFFECT: (and really the whole point of this subroutine) ** @@ -173361,7 +172213,7 @@ static int computeMxChoice(WhereInfo *pWInfo){ } #endif /* SQLITE_DEBUG */ - if( nLoop>=4 /* Constraint (aa) */ + if( nLoop>=5 && !pWInfo->bStarDone && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery) ){ @@ -173373,7 +172225,7 @@ static int computeMxChoice(WhereInfo *pWInfo){ pWInfo->bStarDone = 1; /* Only do this computation once */ - /* Look for fact tables with three or more dimensions where the + /* Look for fact tables with four or more dimensions where the ** dimension tables are not separately from the fact tables by an outer ** or cross join. Adjust cost weights if found. */ @@ -173390,17 +172242,18 @@ static int computeMxChoice(WhereInfo *pWInfo){ if( (pFactTab->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ /* If the candidate fact-table is the right table of an outer join ** restrict the search for dimension-tables to be tables to the right - ** of the fact-table. Constraint (bb) */ - if( iFromIdx+3 > nLoop ){ - break; /* ^-- Impossible to reach nDep>=2 - Constraint (cc) */ - } + ** of the fact-table. */ + if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */ while( pStart && pStart->iTab<=iFromIdx ){ pStart = pStart->pNextLoop; } } for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){ - break; /* Constraint (bb) */ + /* Fact-tables and dimension-tables cannot be separated by an + ** outer join (at least for the definition of fact- and dimension- + ** used by this heuristic). */ + break; } if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */ && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */ @@ -173414,9 +172267,7 @@ static int computeMxChoice(WhereInfo *pWInfo){ } } } - if( nDep<=2 ){ - continue; /* Constraint (cc) */ - } + if( nDep<=3 ) continue; /* If we reach this point, it means that pFactTab is a fact table ** with four or more dimensions connected by inner joins. Proceed @@ -173429,23 +172280,6 @@ static int computeMxChoice(WhereInfo *pWInfo){ pWLoop->rStarDelta = 0; } } -#endif -#ifdef WHERETRACE_ENABLED /* 0x80000 */ - if( sqlite3WhereTrace & 0x80000 ){ - Bitmask mShow = mSeen; - sqlite3DebugPrintf("Fact table %s(%d), dimensions:", - pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, - iFromIdx); - for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){ - if( mShow & pWLoop->maskSelf ){ - SrcItem *pDim = aFromTabs + pWLoop->iTab; - mShow &= ~pWLoop->maskSelf; - sqlite3DebugPrintf(" %s(%d)", - pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab); - } - } - sqlite3DebugPrintf("\n"); - } #endif pWInfo->bStarUsed = 1; @@ -173469,8 +172303,10 @@ static int computeMxChoice(WhereInfo *pWInfo){ if( sqlite3WhereTrace & 0x80000 ){ SrcItem *pDim = aFromTabs + pWLoop->iTab; sqlite3DebugPrintf( - "Increase SCAN cost of %s to %d\n", - pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, mxRun + "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n", + pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab, + pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName, + iFromIdx, mxRun ); } pWLoop->rStarDelta = mxRun - pWLoop->rRun; @@ -174284,7 +173120,6 @@ static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ pTerm->wtFlags |= TERM_CODED; - pTerm->prereqAll = 0; } } if( i!=pWInfo->nLevel-1 ){ @@ -175272,15 +174107,14 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ } - if( pTabList->a[pLevel->iFrom].fg.fromExists - && (i==pWInfo->nLevel-1 - || pTabList->a[pWInfo->a[i+1].iFrom].fg.fromExists==0) - ){ - /* This is an EXISTS-to-JOIN optimization which is either the - ** inner-most loop, or the inner-most of a group of nested - ** EXISTS-to-JOIN optimization loops. If this loop sees a successful - ** row, it should break out of itself as well as other EXISTS-to-JOIN - ** loops in which is is directly nested. */ + if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){ + /* If the EXISTS-to-JOIN optimization was applied, then the EXISTS + ** loop(s) will be the inner-most loops of the join. There might be + ** multiple EXISTS loops, but they will all be nested, and the join + ** order will not have been changed by the query planner. If the + ** inner-most EXISTS loop sees a single successful row, it should + ** break out of *all* EXISTS loops. But only the inner-most of the + ** nested EXISTS loops should do this breakout. */ int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */ while( nOutera[pLevel[-nOuter-1].iFrom].fg.fromExists ) break; @@ -175288,11 +174122,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } testcase( nOuter>0 ); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk); - if( nOuter ){ - VdbeComment((v, "EXISTS break %d..%d", i-nOuter, i)); - }else{ - VdbeComment((v, "EXISTS break %d", i)); - } + VdbeComment((v, "EXISTS break")); } sqlite3VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ @@ -176309,7 +175139,7 @@ SQLITE_PRIVATE void sqlite3WindowUpdate( pWin->eEnd = aUp[i].eEnd; pWin->eExclude = 0; if( pWin->eStart==TK_FOLLOWING ){ - pWin->pStart = sqlite3ExprInt32(db, 1); + pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1"); } break; } @@ -176654,7 +175484,9 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** keep everything legal in this case. */ if( pSublist==0 ){ - pSublist = sqlite3ExprListAppend(pParse, 0, sqlite3ExprInt32(db, 0)); + pSublist = sqlite3ExprListAppend(pParse, 0, + sqlite3Expr(db, TK_INTEGER, "0") + ); } pSub = sqlite3SelectNew( @@ -178878,23 +177710,8 @@ static void updateDeleteLimitError( ** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate ** testing. */ - static void *parserStackRealloc( - void *pOld, /* Prior allocation */ - sqlite3_uint64 newSize, /* Requested new alloation size */ - Parse *pParse /* Parsing context */ - ){ - void *p = sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); - if( p==0 ) sqlite3OomFault(pParse->db); - return p; - } - static void parserStackFree(void *pOld, Parse *pParse){ - (void)pParse; - sqlite3_free(pOld); - } - - /* Return an integer that is the maximum allowed stack size */ - static int parserStackSizeLimit(Parse *pParse){ - return pParse->db->aLimit[SQLITE_LIMIT_PARSER_DEPTH]; + static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){ + return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize); } @@ -178933,46 +177750,15 @@ static void updateDeleteLimitError( } - /* Create a TK_ISNULL or TK_NOTNULL expression, perhaps optimized to - ** to TK_TRUEFALSE, if possible */ - static Expr *sqlite3PExprIsNull( - Parse *pParse, /* Parsing context */ - int op, /* TK_ISNULL or TK_NOTNULL */ - Expr *pLeft /* Operand */ - ){ - Expr *p = pLeft; - assert( op==TK_ISNULL || op==TK_NOTNULL ); - assert( pLeft!=0 ); - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ - p = p->pLeft; - assert( p!=0 ); - } - switch( p->op ){ - case TK_INTEGER: - case TK_STRING: - case TK_FLOAT: - case TK_BLOB: - sqlite3ExprDeferredDelete(pParse, pLeft); - return sqlite3ExprInt32(pParse->db, op==TK_NOTNULL); - default: - break; - } - return sqlite3PExpr(pParse, op, pLeft, 0); - } - - /* Create a TK_IS or TK_ISNOT operator, perhaps optimized to - ** TK_ISNULL or TK_NOTNULL or TK_TRUEFALSE. */ - static Expr *sqlite3PExprIs( - Parse *pParse, /* Parsing context */ - int op, /* TK_IS or TK_ISNOT */ - Expr *pLeft, /* Left operand */ - Expr *pRight /* Right operand */ - ){ - if( pRight && pRight->op==TK_NULL ){ - sqlite3ExprDeferredDelete(pParse, pRight); - return sqlite3PExprIsNull(pParse, op==TK_IS ? TK_ISNULL : TK_NOTNULL, pLeft); + /* A routine to convert a binary TK_IS or TK_ISNOT expression into a + ** unary TK_ISNULL or TK_NOTNULL expression. */ + static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){ + sqlite3 *db = pParse->db; + if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){ + pA->op = (u8)op; + sqlite3ExprDelete(db, pA->pRight); + pA->pRight = 0; } - return sqlite3PExpr(pParse, op, pLeft, pRight); } /* Add a single new term to an ExprList that is used to store a @@ -179255,72 +178041,63 @@ static void updateDeleteLimitError( #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 322 +#define YYNOCODE 323 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 102 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - ExprList* yy14; - With* yy59; - Cte* yy67; - Upsert* yy122; - IdList* yy132; - int yy144; - const char* yy168; - SrcList* yy203; - Window* yy211; - OnOrUsing yy269; - struct TrigEvent yy286; - struct {int value; int mask;} yy383; - u32 yy391; - TriggerStep* yy427; - Expr* yy454; - u8 yy462; - struct FrameBound yy509; - Select* yy555; + u32 yy9; + struct TrigEvent yy28; + With* yy125; + IdList* yy204; + struct FrameBound yy205; + TriggerStep* yy319; + const char* yy342; + Cte* yy361; + ExprList* yy402; + Upsert* yy403; + OnOrUsing yy421; + u8 yy444; + struct {int value; int mask;} yy481; + Window* yy483; + int yy502; + SrcList* yy563; + Expr* yy590; + Select* yy637; } YYMINORTYPE; #ifndef YYSTACKDEPTH -#define YYSTACKDEPTH 50 +#define YYSTACKDEPTH 100 #endif #define sqlite3ParserARG_SDECL #define sqlite3ParserARG_PDECL #define sqlite3ParserARG_PARAM #define sqlite3ParserARG_FETCH #define sqlite3ParserARG_STORE -#undef YYREALLOC #define YYREALLOC parserStackRealloc -#undef YYFREE -#define YYFREE parserStackFree -#undef YYDYNSTACK +#define YYFREE sqlite3_free #define YYDYNSTACK 1 -#undef YYSIZELIMIT -#define YYSIZELIMIT parserStackSizeLimit -#define sqlite3ParserCTX(P) ((P)->pParse) #define sqlite3ParserCTX_SDECL Parse *pParse; #define sqlite3ParserCTX_PDECL ,Parse *pParse #define sqlite3ParserCTX_PARAM ,pParse #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; -#undef YYERRORSYMBOL -#undef YYERRSYMDT -#undef YYFALLBACK #define YYFALLBACK 1 -#define YYNSTATE 600 -#define YYNRULE 412 -#define YYNRULE_WITH_ACTION 348 +#define YYNSTATE 583 +#define YYNRULE 409 +#define YYNRULE_WITH_ACTION 344 #define YYNTOKEN 187 -#define YY_MAX_SHIFT 599 -#define YY_MIN_SHIFTREDUCE 867 -#define YY_MAX_SHIFTREDUCE 1278 -#define YY_ERROR_ACTION 1279 -#define YY_ACCEPT_ACTION 1280 -#define YY_NO_ACTION 1281 -#define YY_MIN_REDUCE 1282 -#define YY_MAX_REDUCE 1693 +#define YY_MAX_SHIFT 582 +#define YY_MIN_SHIFTREDUCE 845 +#define YY_MAX_SHIFTREDUCE 1253 +#define YY_ERROR_ACTION 1254 +#define YY_ACCEPT_ACTION 1255 +#define YY_NO_ACTION 1256 +#define YY_MIN_REDUCE 1257 +#define YY_MAX_REDUCE 1665 #define YY_MIN_DSTRCTR 206 -#define YY_MAX_DSTRCTR 319 +#define YY_MAX_DSTRCTR 320 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -179403,680 +178180,643 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2379) +#define YY_ACTTAB_COUNT (2207) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 134, 131, 238, 290, 290, 1353, 593, 1332, 478, 1606, - /* 10 */ 593, 1315, 593, 7, 593, 1353, 590, 593, 579, 424, - /* 20 */ 1566, 134, 131, 238, 1318, 541, 478, 477, 575, 84, - /* 30 */ 84, 1005, 303, 84, 84, 51, 51, 63, 63, 1006, - /* 40 */ 84, 84, 498, 141, 142, 93, 442, 1254, 1254, 1085, - /* 50 */ 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, 424, - /* 60 */ 296, 296, 498, 296, 296, 567, 553, 296, 296, 1306, - /* 70 */ 574, 1358, 1358, 590, 542, 579, 590, 574, 579, 548, - /* 80 */ 590, 1304, 579, 141, 142, 93, 576, 1254, 1254, 1085, - /* 90 */ 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, 399, - /* 100 */ 478, 395, 6, 138, 138, 138, 138, 137, 137, 136, - /* 110 */ 136, 136, 135, 132, 463, 44, 342, 593, 305, 1127, - /* 120 */ 1280, 1, 1, 599, 2, 1284, 598, 1200, 1284, 1200, - /* 130 */ 330, 424, 158, 330, 1613, 158, 390, 116, 308, 1366, - /* 140 */ 51, 51, 1366, 138, 138, 138, 138, 137, 137, 136, - /* 150 */ 136, 136, 135, 132, 463, 141, 142, 93, 515, 1254, - /* 160 */ 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, - /* 170 */ 140, 1230, 329, 584, 296, 296, 212, 296, 296, 568, - /* 180 */ 568, 488, 143, 1072, 1072, 1086, 1089, 590, 1195, 579, - /* 190 */ 590, 340, 579, 140, 140, 140, 140, 133, 392, 564, - /* 200 */ 536, 1195, 250, 425, 1195, 250, 137, 137, 136, 136, - /* 210 */ 136, 135, 132, 463, 291, 138, 138, 138, 138, 137, - /* 220 */ 137, 136, 136, 136, 135, 132, 463, 966, 1230, 1231, - /* 230 */ 1230, 412, 965, 467, 412, 424, 467, 489, 357, 1611, - /* 240 */ 391, 138, 138, 138, 138, 137, 137, 136, 136, 136, - /* 250 */ 135, 132, 463, 463, 134, 131, 238, 555, 1076, 141, - /* 260 */ 142, 93, 593, 1254, 1254, 1085, 1088, 1075, 1075, 139, - /* 270 */ 139, 140, 140, 140, 140, 1317, 134, 131, 238, 424, - /* 280 */ 549, 1597, 1531, 333, 97, 83, 83, 140, 140, 140, - /* 290 */ 140, 138, 138, 138, 138, 137, 137, 136, 136, 136, - /* 300 */ 135, 132, 463, 141, 142, 93, 1657, 1254, 1254, 1085, - /* 310 */ 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, 138, - /* 320 */ 138, 138, 138, 137, 137, 136, 136, 136, 135, 132, - /* 330 */ 463, 591, 1230, 958, 958, 138, 138, 138, 138, 137, - /* 340 */ 137, 136, 136, 136, 135, 132, 463, 44, 398, 547, - /* 350 */ 1306, 136, 136, 136, 135, 132, 463, 386, 593, 442, - /* 360 */ 595, 145, 595, 138, 138, 138, 138, 137, 137, 136, - /* 370 */ 136, 136, 135, 132, 463, 500, 1230, 112, 550, 460, - /* 380 */ 459, 51, 51, 424, 296, 296, 479, 334, 1259, 1230, - /* 390 */ 1231, 1230, 1599, 1261, 388, 312, 444, 590, 246, 579, - /* 400 */ 546, 1260, 271, 235, 329, 584, 551, 141, 142, 93, - /* 410 */ 429, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, - /* 420 */ 140, 140, 140, 22, 22, 1230, 1262, 424, 1262, 216, - /* 430 */ 296, 296, 98, 1230, 1231, 1230, 264, 884, 45, 528, - /* 440 */ 525, 524, 1041, 590, 1269, 579, 421, 420, 393, 523, - /* 450 */ 44, 141, 142, 93, 498, 1254, 1254, 1085, 1088, 1075, - /* 460 */ 1075, 139, 139, 140, 140, 140, 140, 138, 138, 138, - /* 470 */ 138, 137, 137, 136, 136, 136, 135, 132, 463, 593, - /* 480 */ 1611, 561, 1230, 1231, 1230, 23, 264, 515, 200, 528, - /* 490 */ 525, 524, 127, 585, 509, 4, 355, 487, 506, 523, - /* 500 */ 593, 498, 84, 84, 134, 131, 238, 329, 584, 588, - /* 510 */ 1627, 138, 138, 138, 138, 137, 137, 136, 136, 136, - /* 520 */ 135, 132, 463, 19, 19, 435, 1230, 1460, 297, 297, - /* 530 */ 311, 424, 1565, 464, 1631, 599, 2, 1284, 437, 574, - /* 540 */ 1107, 590, 330, 579, 158, 582, 489, 357, 573, 593, - /* 550 */ 592, 1366, 409, 1274, 1230, 141, 142, 93, 1364, 1254, - /* 560 */ 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, - /* 570 */ 140, 389, 84, 84, 1062, 567, 1230, 313, 1523, 593, - /* 580 */ 125, 125, 970, 1230, 1231, 1230, 296, 296, 126, 46, - /* 590 */ 464, 594, 464, 296, 296, 1050, 1230, 218, 439, 590, - /* 600 */ 1604, 579, 84, 84, 7, 403, 590, 515, 579, 325, - /* 610 */ 417, 1230, 1231, 1230, 250, 138, 138, 138, 138, 137, - /* 620 */ 137, 136, 136, 136, 135, 132, 463, 1050, 1050, 1052, - /* 630 */ 1053, 35, 1275, 1230, 1231, 1230, 424, 1370, 993, 574, - /* 640 */ 371, 414, 274, 412, 1597, 467, 1302, 552, 451, 590, - /* 650 */ 543, 579, 1530, 1230, 1231, 1230, 1214, 201, 409, 1174, - /* 660 */ 141, 142, 93, 223, 1254, 1254, 1085, 1088, 1075, 1075, - /* 670 */ 139, 139, 140, 140, 140, 140, 296, 296, 1250, 593, - /* 680 */ 424, 296, 296, 236, 529, 296, 296, 515, 100, 590, - /* 690 */ 1600, 579, 48, 1605, 590, 1230, 579, 7, 590, 577, - /* 700 */ 579, 904, 84, 84, 141, 142, 93, 496, 1254, 1254, - /* 710 */ 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, - /* 720 */ 138, 138, 138, 138, 137, 137, 136, 136, 136, 135, - /* 730 */ 132, 463, 1365, 1230, 296, 296, 1250, 115, 1275, 326, - /* 740 */ 233, 539, 1062, 40, 282, 127, 585, 590, 4, 579, - /* 750 */ 329, 584, 1230, 1231, 1230, 1598, 593, 388, 904, 1051, - /* 760 */ 1356, 1356, 588, 1050, 138, 138, 138, 138, 137, 137, - /* 770 */ 136, 136, 136, 135, 132, 463, 185, 593, 1230, 19, - /* 780 */ 19, 1230, 971, 1597, 424, 1651, 464, 129, 908, 1195, - /* 790 */ 1230, 1231, 1230, 1325, 443, 1050, 1050, 1052, 582, 1603, - /* 800 */ 149, 149, 1195, 7, 5, 1195, 1687, 410, 141, 142, - /* 810 */ 93, 1536, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, - /* 820 */ 140, 140, 140, 140, 1214, 397, 593, 1062, 424, 1536, - /* 830 */ 1538, 50, 901, 125, 125, 1230, 1231, 1230, 1230, 1231, - /* 840 */ 1230, 126, 1230, 464, 594, 464, 515, 1230, 1050, 84, - /* 850 */ 84, 3, 141, 142, 93, 924, 1254, 1254, 1085, 1088, - /* 860 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 138, 138, - /* 870 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 463, - /* 880 */ 1050, 1050, 1052, 1053, 35, 442, 457, 532, 433, 1230, - /* 890 */ 1062, 1361, 540, 540, 1598, 925, 388, 7, 1129, 1230, - /* 900 */ 1231, 1230, 1129, 1536, 1230, 1231, 1230, 1051, 570, 1214, - /* 910 */ 593, 1050, 138, 138, 138, 138, 137, 137, 136, 136, - /* 920 */ 136, 135, 132, 463, 6, 185, 1195, 1230, 231, 593, - /* 930 */ 382, 992, 424, 151, 151, 510, 1213, 557, 482, 1195, - /* 940 */ 381, 160, 1195, 1050, 1050, 1052, 1230, 1231, 1230, 422, - /* 950 */ 593, 447, 84, 84, 593, 217, 141, 142, 93, 593, - /* 960 */ 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, - /* 970 */ 140, 140, 1214, 19, 19, 593, 424, 19, 19, 442, - /* 980 */ 1063, 442, 19, 19, 1230, 1231, 1230, 515, 445, 458, - /* 990 */ 1597, 386, 315, 1175, 1685, 556, 1685, 450, 84, 84, - /* 1000 */ 141, 142, 93, 505, 1254, 1254, 1085, 1088, 1075, 1075, - /* 1010 */ 139, 139, 140, 140, 140, 140, 138, 138, 138, 138, - /* 1020 */ 137, 137, 136, 136, 136, 135, 132, 463, 442, 1147, - /* 1030 */ 454, 1597, 362, 1041, 593, 462, 1460, 1233, 47, 1393, - /* 1040 */ 324, 565, 565, 115, 1148, 449, 7, 460, 459, 307, - /* 1050 */ 375, 354, 593, 113, 593, 329, 584, 19, 19, 1149, - /* 1060 */ 138, 138, 138, 138, 137, 137, 136, 136, 136, 135, - /* 1070 */ 132, 463, 209, 1173, 563, 19, 19, 19, 19, 49, - /* 1080 */ 424, 944, 1175, 1686, 1046, 1686, 218, 355, 484, 343, - /* 1090 */ 210, 945, 569, 562, 1262, 1233, 1262, 490, 314, 423, - /* 1100 */ 424, 1598, 1206, 388, 141, 142, 93, 440, 1254, 1254, - /* 1110 */ 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, - /* 1120 */ 352, 316, 531, 316, 141, 142, 93, 549, 1254, 1254, - /* 1130 */ 1085, 1088, 1075, 1075, 139, 139, 140, 140, 140, 140, - /* 1140 */ 446, 10, 1598, 274, 388, 915, 281, 299, 383, 534, - /* 1150 */ 378, 533, 269, 593, 1206, 587, 587, 587, 374, 293, - /* 1160 */ 1579, 991, 1173, 302, 138, 138, 138, 138, 137, 137, - /* 1170 */ 136, 136, 136, 135, 132, 463, 53, 53, 520, 1250, - /* 1180 */ 593, 1147, 1576, 431, 138, 138, 138, 138, 137, 137, - /* 1190 */ 136, 136, 136, 135, 132, 463, 1148, 301, 593, 1577, - /* 1200 */ 593, 1307, 431, 54, 54, 593, 268, 593, 461, 461, - /* 1210 */ 461, 1149, 347, 492, 424, 135, 132, 463, 1146, 1195, - /* 1220 */ 474, 68, 68, 69, 69, 550, 332, 287, 21, 21, - /* 1230 */ 55, 55, 1195, 581, 424, 1195, 309, 1250, 141, 142, - /* 1240 */ 93, 119, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, - /* 1250 */ 140, 140, 140, 140, 593, 237, 480, 1476, 141, 142, - /* 1260 */ 93, 593, 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, - /* 1270 */ 140, 140, 140, 140, 344, 430, 346, 70, 70, 494, - /* 1280 */ 991, 1132, 1132, 512, 56, 56, 1269, 593, 268, 593, - /* 1290 */ 369, 374, 593, 481, 215, 384, 1624, 481, 138, 138, - /* 1300 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 463, - /* 1310 */ 71, 71, 72, 72, 225, 73, 73, 593, 138, 138, - /* 1320 */ 138, 138, 137, 137, 136, 136, 136, 135, 132, 463, - /* 1330 */ 586, 431, 593, 872, 873, 874, 593, 911, 593, 1602, - /* 1340 */ 74, 74, 593, 7, 1460, 242, 593, 306, 424, 1578, - /* 1350 */ 472, 306, 364, 219, 367, 75, 75, 430, 345, 57, - /* 1360 */ 57, 58, 58, 432, 187, 59, 59, 593, 424, 61, - /* 1370 */ 61, 1475, 141, 142, 93, 123, 1254, 1254, 1085, 1088, - /* 1380 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 424, 570, - /* 1390 */ 62, 62, 141, 142, 93, 911, 1254, 1254, 1085, 1088, - /* 1400 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 161, 384, - /* 1410 */ 1624, 1474, 141, 130, 93, 441, 1254, 1254, 1085, 1088, - /* 1420 */ 1075, 1075, 139, 139, 140, 140, 140, 140, 267, 266, - /* 1430 */ 265, 1460, 138, 138, 138, 138, 137, 137, 136, 136, - /* 1440 */ 136, 135, 132, 463, 593, 1336, 593, 1269, 1460, 384, - /* 1450 */ 1624, 231, 138, 138, 138, 138, 137, 137, 136, 136, - /* 1460 */ 136, 135, 132, 463, 593, 163, 593, 76, 76, 77, - /* 1470 */ 77, 593, 138, 138, 138, 138, 137, 137, 136, 136, - /* 1480 */ 136, 135, 132, 463, 475, 593, 483, 78, 78, 20, - /* 1490 */ 20, 1249, 424, 491, 79, 79, 495, 422, 295, 235, - /* 1500 */ 1574, 38, 511, 896, 422, 335, 240, 422, 147, 147, - /* 1510 */ 112, 593, 424, 593, 101, 222, 991, 142, 93, 455, - /* 1520 */ 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, - /* 1530 */ 140, 140, 593, 39, 148, 148, 80, 80, 93, 551, - /* 1540 */ 1254, 1254, 1085, 1088, 1075, 1075, 139, 139, 140, 140, - /* 1550 */ 140, 140, 328, 923, 922, 64, 64, 502, 1656, 1005, - /* 1560 */ 933, 896, 124, 422, 121, 254, 593, 1006, 593, 226, - /* 1570 */ 593, 127, 585, 164, 4, 16, 138, 138, 138, 138, - /* 1580 */ 137, 137, 136, 136, 136, 135, 132, 463, 588, 81, - /* 1590 */ 81, 65, 65, 82, 82, 593, 138, 138, 138, 138, - /* 1600 */ 137, 137, 136, 136, 136, 135, 132, 463, 593, 226, - /* 1610 */ 237, 966, 464, 593, 298, 593, 965, 593, 66, 66, - /* 1620 */ 593, 1170, 593, 411, 582, 353, 469, 115, 593, 471, - /* 1630 */ 169, 173, 173, 593, 44, 991, 174, 174, 89, 89, - /* 1640 */ 67, 67, 593, 85, 85, 150, 150, 1114, 1043, 593, - /* 1650 */ 273, 86, 86, 1062, 593, 503, 171, 171, 593, 125, - /* 1660 */ 125, 497, 593, 273, 336, 152, 152, 126, 1335, 464, - /* 1670 */ 594, 464, 146, 146, 1050, 593, 545, 172, 172, 593, - /* 1680 */ 1054, 165, 165, 256, 339, 156, 156, 127, 585, 1586, - /* 1690 */ 4, 329, 584, 499, 358, 273, 115, 348, 155, 155, - /* 1700 */ 930, 931, 153, 153, 588, 1114, 1050, 1050, 1052, 1053, - /* 1710 */ 35, 1554, 521, 593, 270, 1008, 1009, 9, 593, 372, - /* 1720 */ 593, 115, 593, 168, 593, 115, 593, 1110, 464, 270, - /* 1730 */ 996, 964, 273, 129, 1645, 1214, 154, 154, 1054, 1404, - /* 1740 */ 582, 88, 88, 90, 90, 87, 87, 52, 52, 60, - /* 1750 */ 60, 1405, 504, 537, 559, 1179, 961, 507, 129, 558, - /* 1760 */ 127, 585, 1126, 4, 1126, 1125, 894, 1125, 162, 1062, - /* 1770 */ 963, 359, 129, 1401, 363, 125, 125, 588, 366, 368, - /* 1780 */ 370, 1349, 1334, 126, 1333, 464, 594, 464, 377, 387, - /* 1790 */ 1050, 1391, 1414, 1618, 1459, 1387, 1399, 208, 580, 1464, - /* 1800 */ 1314, 464, 243, 516, 1305, 1293, 1384, 1292, 1294, 1638, - /* 1810 */ 288, 170, 228, 582, 12, 408, 321, 322, 241, 323, - /* 1820 */ 245, 1446, 1050, 1050, 1052, 1053, 35, 559, 304, 350, - /* 1830 */ 351, 501, 560, 127, 585, 1441, 4, 1451, 1434, 310, - /* 1840 */ 1450, 526, 1062, 1332, 415, 380, 232, 1527, 125, 125, - /* 1850 */ 588, 1214, 1396, 356, 1526, 583, 126, 1397, 464, 594, - /* 1860 */ 464, 1641, 535, 1050, 1581, 1395, 1269, 1583, 1582, 213, - /* 1870 */ 402, 277, 214, 227, 464, 1573, 239, 1571, 1266, 1394, - /* 1880 */ 434, 198, 100, 224, 96, 183, 582, 191, 485, 193, - /* 1890 */ 486, 194, 195, 196, 519, 1050, 1050, 1052, 1053, 35, - /* 1900 */ 559, 113, 252, 413, 1447, 558, 493, 13, 1455, 416, - /* 1910 */ 1453, 1452, 14, 202, 1521, 1062, 1532, 508, 258, 106, - /* 1920 */ 514, 125, 125, 99, 1214, 1543, 289, 260, 206, 126, - /* 1930 */ 365, 464, 594, 464, 361, 517, 1050, 261, 448, 1295, - /* 1940 */ 262, 418, 1352, 1351, 108, 1350, 1655, 1654, 1343, 915, - /* 1950 */ 419, 1322, 233, 452, 319, 379, 1321, 453, 1623, 320, - /* 1960 */ 1320, 275, 1653, 544, 276, 1609, 1608, 1342, 1050, 1050, - /* 1970 */ 1052, 1053, 35, 1630, 1218, 466, 385, 456, 300, 1419, - /* 1980 */ 144, 1418, 570, 407, 407, 406, 284, 404, 11, 1508, - /* 1990 */ 881, 396, 120, 127, 585, 394, 4, 1214, 327, 114, - /* 2000 */ 1375, 1374, 220, 247, 400, 338, 401, 554, 42, 1224, - /* 2010 */ 588, 596, 283, 337, 285, 286, 188, 597, 1290, 1285, - /* 2020 */ 175, 1558, 176, 1559, 1557, 1556, 159, 317, 229, 177, - /* 2030 */ 868, 230, 91, 465, 464, 221, 331, 468, 1165, 470, - /* 2040 */ 473, 94, 244, 95, 249, 189, 582, 1124, 1122, 341, - /* 2050 */ 427, 190, 178, 1249, 179, 43, 192, 947, 349, 428, - /* 2060 */ 1138, 197, 251, 180, 181, 436, 102, 182, 438, 103, - /* 2070 */ 104, 199, 248, 1140, 253, 1062, 105, 255, 1137, 166, - /* 2080 */ 24, 125, 125, 257, 1264, 273, 360, 513, 259, 126, - /* 2090 */ 15, 464, 594, 464, 204, 883, 1050, 518, 263, 373, - /* 2100 */ 381, 92, 585, 1130, 4, 203, 205, 426, 107, 522, - /* 2110 */ 25, 26, 329, 584, 913, 572, 527, 376, 588, 926, - /* 2120 */ 530, 109, 184, 318, 167, 110, 27, 538, 1050, 1050, - /* 2130 */ 1052, 1053, 35, 1211, 1091, 17, 476, 111, 1181, 234, - /* 2140 */ 292, 1180, 464, 294, 207, 994, 129, 1201, 272, 1000, - /* 2150 */ 28, 1197, 29, 30, 582, 1199, 1205, 1214, 31, 1204, - /* 2160 */ 32, 1186, 41, 566, 33, 1105, 211, 8, 115, 1092, - /* 2170 */ 1090, 1094, 34, 278, 578, 1095, 117, 122, 118, 1145, - /* 2180 */ 36, 18, 128, 1062, 1055, 895, 957, 37, 589, 125, - /* 2190 */ 125, 279, 186, 280, 1646, 157, 405, 126, 1220, 464, - /* 2200 */ 594, 464, 1218, 466, 1050, 1219, 300, 1281, 1281, 1281, - /* 2210 */ 1281, 407, 407, 406, 284, 404, 1281, 1281, 881, 1281, - /* 2220 */ 300, 1281, 1281, 571, 1281, 407, 407, 406, 284, 404, - /* 2230 */ 1281, 247, 881, 338, 1281, 1281, 1050, 1050, 1052, 1053, - /* 2240 */ 35, 337, 1281, 1281, 1281, 247, 1281, 338, 1281, 1281, - /* 2250 */ 1281, 1281, 1281, 1281, 1281, 337, 1281, 1281, 1281, 1281, - /* 2260 */ 1281, 1281, 1281, 1281, 1281, 1214, 1281, 1281, 1281, 1281, - /* 2270 */ 1281, 1281, 249, 1281, 1281, 1281, 1281, 1281, 1281, 1281, - /* 2280 */ 178, 1281, 1281, 43, 1281, 1281, 249, 1281, 1281, 1281, - /* 2290 */ 1281, 1281, 1281, 1281, 178, 1281, 1281, 43, 1281, 1281, - /* 2300 */ 248, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, - /* 2310 */ 1281, 1281, 1281, 1281, 248, 1281, 1281, 1281, 1281, 1281, - /* 2320 */ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, - /* 2330 */ 1281, 1281, 1281, 1281, 1281, 426, 1281, 1281, 1281, 1281, - /* 2340 */ 329, 584, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 426, - /* 2350 */ 1281, 1281, 1281, 1281, 329, 584, 1281, 1281, 1281, 1281, - /* 2360 */ 1281, 1281, 1281, 1281, 476, 1281, 1281, 1281, 1281, 1281, - /* 2370 */ 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 476, + /* 0 */ 130, 127, 234, 282, 282, 1328, 576, 1307, 460, 289, + /* 10 */ 289, 576, 1622, 381, 576, 1328, 573, 576, 562, 413, + /* 20 */ 1300, 1542, 573, 481, 562, 524, 460, 459, 558, 82, + /* 30 */ 82, 983, 294, 375, 51, 51, 498, 61, 61, 984, + /* 40 */ 82, 82, 1577, 137, 138, 91, 7, 1228, 1228, 1063, + /* 50 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 413, + /* 60 */ 288, 288, 182, 288, 288, 481, 536, 288, 288, 130, + /* 70 */ 127, 234, 432, 573, 525, 562, 573, 557, 562, 1290, + /* 80 */ 573, 421, 562, 137, 138, 91, 559, 1228, 1228, 1063, + /* 90 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 296, + /* 100 */ 460, 398, 1249, 134, 134, 134, 134, 133, 133, 132, + /* 110 */ 132, 132, 131, 128, 451, 451, 1050, 1050, 1064, 1067, + /* 120 */ 1255, 1, 1, 582, 2, 1259, 581, 1174, 1259, 1174, + /* 130 */ 321, 413, 155, 321, 1584, 155, 379, 112, 481, 1341, + /* 140 */ 456, 299, 1341, 134, 134, 134, 134, 133, 133, 132, + /* 150 */ 132, 132, 131, 128, 451, 137, 138, 91, 498, 1228, + /* 160 */ 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, + /* 170 */ 136, 1204, 862, 1281, 288, 288, 283, 288, 288, 523, + /* 180 */ 523, 1250, 139, 578, 7, 578, 1345, 573, 1169, 562, + /* 190 */ 573, 1054, 562, 136, 136, 136, 136, 129, 573, 547, + /* 200 */ 562, 1169, 245, 1541, 1169, 245, 133, 133, 132, 132, + /* 210 */ 132, 131, 128, 451, 302, 134, 134, 134, 134, 133, + /* 220 */ 133, 132, 132, 132, 131, 128, 451, 1575, 1204, 1205, + /* 230 */ 1204, 7, 470, 550, 455, 413, 550, 455, 130, 127, + /* 240 */ 234, 134, 134, 134, 134, 133, 133, 132, 132, 132, + /* 250 */ 131, 128, 451, 136, 136, 136, 136, 538, 483, 137, + /* 260 */ 138, 91, 1019, 1228, 1228, 1063, 1066, 1053, 1053, 135, + /* 270 */ 135, 136, 136, 136, 136, 1085, 576, 1204, 132, 132, + /* 280 */ 132, 131, 128, 451, 93, 214, 134, 134, 134, 134, + /* 290 */ 133, 133, 132, 132, 132, 131, 128, 451, 401, 19, + /* 300 */ 19, 134, 134, 134, 134, 133, 133, 132, 132, 132, + /* 310 */ 131, 128, 451, 1498, 426, 267, 344, 467, 332, 134, + /* 320 */ 134, 134, 134, 133, 133, 132, 132, 132, 131, 128, + /* 330 */ 451, 1281, 576, 6, 1204, 1205, 1204, 257, 576, 413, + /* 340 */ 511, 508, 507, 1279, 94, 1019, 464, 1204, 551, 551, + /* 350 */ 506, 1224, 1571, 44, 38, 51, 51, 411, 576, 413, + /* 360 */ 45, 51, 51, 137, 138, 91, 530, 1228, 1228, 1063, + /* 370 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 398, + /* 380 */ 1148, 82, 82, 137, 138, 91, 39, 1228, 1228, 1063, + /* 390 */ 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, 344, + /* 400 */ 44, 288, 288, 375, 1204, 1205, 1204, 209, 1204, 1224, + /* 410 */ 320, 567, 471, 576, 573, 576, 562, 576, 316, 264, + /* 420 */ 231, 46, 160, 134, 134, 134, 134, 133, 133, 132, + /* 430 */ 132, 132, 131, 128, 451, 303, 82, 82, 82, 82, + /* 440 */ 82, 82, 442, 134, 134, 134, 134, 133, 133, 132, + /* 450 */ 132, 132, 131, 128, 451, 1582, 544, 320, 567, 1250, + /* 460 */ 874, 1582, 380, 382, 413, 1204, 1205, 1204, 360, 182, + /* 470 */ 288, 288, 1576, 557, 1339, 557, 7, 557, 1277, 472, + /* 480 */ 346, 526, 531, 573, 556, 562, 439, 1511, 137, 138, + /* 490 */ 91, 219, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, + /* 500 */ 136, 136, 136, 136, 465, 1511, 1513, 532, 413, 288, + /* 510 */ 288, 423, 512, 288, 288, 411, 288, 288, 874, 130, + /* 520 */ 127, 234, 573, 1107, 562, 1204, 573, 1107, 562, 573, + /* 530 */ 560, 562, 137, 138, 91, 1293, 1228, 1228, 1063, 1066, + /* 540 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 134, 134, + /* 550 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, + /* 560 */ 493, 503, 1292, 1204, 257, 288, 288, 511, 508, 507, + /* 570 */ 1204, 1628, 1169, 123, 568, 275, 4, 506, 573, 1511, + /* 580 */ 562, 331, 1204, 1205, 1204, 1169, 548, 548, 1169, 261, + /* 590 */ 571, 7, 134, 134, 134, 134, 133, 133, 132, 132, + /* 600 */ 132, 131, 128, 451, 108, 533, 130, 127, 234, 1204, + /* 610 */ 448, 447, 413, 1451, 452, 983, 886, 96, 1598, 1233, + /* 620 */ 1204, 1205, 1204, 984, 1235, 1450, 565, 1204, 1205, 1204, + /* 630 */ 229, 522, 1234, 534, 1333, 1333, 137, 138, 91, 1449, + /* 640 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, + /* 650 */ 136, 136, 373, 1595, 971, 1040, 413, 1236, 418, 1236, + /* 660 */ 879, 121, 121, 948, 373, 1595, 1204, 1205, 1204, 122, + /* 670 */ 1204, 452, 577, 452, 363, 417, 1028, 882, 373, 1595, + /* 680 */ 137, 138, 91, 462, 1228, 1228, 1063, 1066, 1053, 1053, + /* 690 */ 135, 135, 136, 136, 136, 136, 134, 134, 134, 134, + /* 700 */ 133, 133, 132, 132, 132, 131, 128, 451, 1028, 1028, + /* 710 */ 1030, 1031, 35, 570, 570, 570, 197, 423, 1040, 198, + /* 720 */ 1204, 123, 568, 1204, 4, 320, 567, 1204, 1205, 1204, + /* 730 */ 40, 388, 576, 384, 882, 1029, 423, 1188, 571, 1028, + /* 740 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 750 */ 128, 451, 529, 1568, 1204, 19, 19, 1204, 575, 492, + /* 760 */ 413, 157, 452, 489, 1187, 1331, 1331, 5, 1204, 949, + /* 770 */ 431, 1028, 1028, 1030, 565, 22, 22, 1204, 1205, 1204, + /* 780 */ 1204, 1205, 1204, 477, 137, 138, 91, 212, 1228, 1228, + /* 790 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, + /* 800 */ 1188, 48, 111, 1040, 413, 1204, 213, 970, 1041, 121, + /* 810 */ 121, 1204, 1205, 1204, 1204, 1205, 1204, 122, 221, 452, + /* 820 */ 577, 452, 44, 487, 1028, 1204, 1205, 1204, 137, 138, + /* 830 */ 91, 378, 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, + /* 840 */ 136, 136, 136, 136, 134, 134, 134, 134, 133, 133, + /* 850 */ 132, 132, 132, 131, 128, 451, 1028, 1028, 1030, 1031, + /* 860 */ 35, 461, 1204, 1205, 1204, 1569, 1040, 377, 214, 1149, + /* 870 */ 1657, 535, 1657, 437, 902, 320, 567, 1568, 364, 320, + /* 880 */ 567, 412, 329, 1029, 519, 1188, 3, 1028, 134, 134, + /* 890 */ 134, 134, 133, 133, 132, 132, 132, 131, 128, 451, + /* 900 */ 1659, 399, 1169, 307, 893, 307, 515, 576, 413, 214, + /* 910 */ 498, 944, 1024, 540, 903, 1169, 943, 392, 1169, 1028, + /* 920 */ 1028, 1030, 406, 298, 1204, 50, 1149, 1658, 413, 1658, + /* 930 */ 145, 145, 137, 138, 91, 293, 1228, 1228, 1063, 1066, + /* 940 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 1188, 1147, + /* 950 */ 514, 1568, 137, 138, 91, 1505, 1228, 1228, 1063, 1066, + /* 960 */ 1053, 1053, 135, 135, 136, 136, 136, 136, 434, 323, + /* 970 */ 435, 539, 111, 1506, 274, 291, 372, 517, 367, 516, + /* 980 */ 262, 1204, 1205, 1204, 1574, 481, 363, 576, 7, 1569, + /* 990 */ 1568, 377, 134, 134, 134, 134, 133, 133, 132, 132, + /* 1000 */ 132, 131, 128, 451, 1568, 576, 1147, 576, 232, 576, + /* 1010 */ 19, 19, 134, 134, 134, 134, 133, 133, 132, 132, + /* 1020 */ 132, 131, 128, 451, 1169, 433, 576, 1207, 19, 19, + /* 1030 */ 19, 19, 19, 19, 1627, 576, 911, 1169, 47, 120, + /* 1040 */ 1169, 117, 413, 306, 498, 438, 1125, 206, 336, 19, + /* 1050 */ 19, 1435, 49, 449, 449, 449, 1368, 315, 81, 81, + /* 1060 */ 576, 304, 413, 1570, 207, 377, 137, 138, 91, 115, + /* 1070 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, + /* 1080 */ 136, 136, 576, 82, 82, 1207, 137, 138, 91, 1340, + /* 1090 */ 1228, 1228, 1063, 1066, 1053, 1053, 135, 135, 136, 136, + /* 1100 */ 136, 136, 1569, 386, 377, 82, 82, 463, 1126, 1552, + /* 1110 */ 333, 463, 335, 131, 128, 451, 1569, 161, 377, 16, + /* 1120 */ 317, 387, 428, 1127, 448, 447, 134, 134, 134, 134, + /* 1130 */ 133, 133, 132, 132, 132, 131, 128, 451, 1128, 576, + /* 1140 */ 1105, 10, 445, 267, 576, 1554, 134, 134, 134, 134, + /* 1150 */ 133, 133, 132, 132, 132, 131, 128, 451, 532, 576, + /* 1160 */ 922, 576, 19, 19, 576, 1573, 576, 147, 147, 7, + /* 1170 */ 923, 1236, 498, 1236, 576, 487, 413, 552, 285, 1224, + /* 1180 */ 969, 215, 82, 82, 66, 66, 1435, 67, 67, 21, + /* 1190 */ 21, 1110, 1110, 495, 334, 297, 413, 53, 53, 297, + /* 1200 */ 137, 138, 91, 119, 1228, 1228, 1063, 1066, 1053, 1053, + /* 1210 */ 135, 135, 136, 136, 136, 136, 413, 1336, 1311, 446, + /* 1220 */ 137, 138, 91, 227, 1228, 1228, 1063, 1066, 1053, 1053, + /* 1230 */ 135, 135, 136, 136, 136, 136, 574, 1224, 936, 936, + /* 1240 */ 137, 126, 91, 141, 1228, 1228, 1063, 1066, 1053, 1053, + /* 1250 */ 135, 135, 136, 136, 136, 136, 533, 429, 472, 346, + /* 1260 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 1270 */ 128, 451, 576, 457, 233, 343, 1435, 403, 498, 1550, + /* 1280 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 1290 */ 128, 451, 576, 324, 576, 82, 82, 487, 576, 969, + /* 1300 */ 134, 134, 134, 134, 133, 133, 132, 132, 132, 131, + /* 1310 */ 128, 451, 288, 288, 546, 68, 68, 54, 54, 553, + /* 1320 */ 413, 69, 69, 351, 6, 573, 944, 562, 410, 409, + /* 1330 */ 1435, 943, 450, 545, 260, 259, 258, 576, 158, 576, + /* 1340 */ 413, 222, 1180, 479, 969, 138, 91, 430, 1228, 1228, + /* 1350 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, + /* 1360 */ 70, 70, 71, 71, 576, 1126, 91, 576, 1228, 1228, + /* 1370 */ 1063, 1066, 1053, 1053, 135, 135, 136, 136, 136, 136, + /* 1380 */ 1127, 166, 850, 851, 852, 1282, 419, 72, 72, 108, + /* 1390 */ 73, 73, 1310, 358, 1180, 1128, 576, 305, 576, 123, + /* 1400 */ 568, 494, 4, 488, 134, 134, 134, 134, 133, 133, + /* 1410 */ 132, 132, 132, 131, 128, 451, 571, 564, 534, 55, + /* 1420 */ 55, 56, 56, 576, 134, 134, 134, 134, 133, 133, + /* 1430 */ 132, 132, 132, 131, 128, 451, 576, 1104, 233, 1104, + /* 1440 */ 452, 1602, 582, 2, 1259, 576, 57, 57, 576, 321, + /* 1450 */ 576, 155, 565, 1435, 485, 353, 576, 356, 1341, 59, + /* 1460 */ 59, 576, 44, 969, 569, 419, 576, 238, 60, 60, + /* 1470 */ 261, 74, 74, 75, 75, 287, 231, 576, 1366, 76, + /* 1480 */ 76, 1040, 420, 184, 20, 20, 576, 121, 121, 77, + /* 1490 */ 77, 97, 218, 288, 288, 122, 125, 452, 577, 452, + /* 1500 */ 143, 143, 1028, 576, 520, 576, 573, 576, 562, 144, + /* 1510 */ 144, 474, 227, 1244, 478, 123, 568, 576, 4, 320, + /* 1520 */ 567, 245, 411, 576, 443, 411, 78, 78, 62, 62, + /* 1530 */ 79, 79, 571, 319, 1028, 1028, 1030, 1031, 35, 418, + /* 1540 */ 63, 63, 576, 290, 411, 9, 80, 80, 1144, 576, + /* 1550 */ 400, 576, 486, 455, 576, 1223, 452, 576, 325, 342, + /* 1560 */ 576, 111, 576, 1188, 242, 64, 64, 473, 565, 576, + /* 1570 */ 23, 576, 170, 170, 171, 171, 576, 87, 87, 328, + /* 1580 */ 65, 65, 542, 83, 83, 146, 146, 541, 123, 568, + /* 1590 */ 341, 4, 84, 84, 168, 168, 576, 1040, 576, 148, + /* 1600 */ 148, 576, 1380, 121, 121, 571, 1021, 576, 266, 576, + /* 1610 */ 424, 122, 576, 452, 577, 452, 576, 553, 1028, 142, + /* 1620 */ 142, 169, 169, 576, 162, 162, 528, 889, 371, 452, + /* 1630 */ 152, 152, 151, 151, 1379, 149, 149, 109, 370, 150, + /* 1640 */ 150, 565, 576, 480, 576, 266, 86, 86, 576, 1092, + /* 1650 */ 1028, 1028, 1030, 1031, 35, 542, 482, 576, 266, 466, + /* 1660 */ 543, 123, 568, 1616, 4, 88, 88, 85, 85, 475, + /* 1670 */ 1040, 52, 52, 222, 901, 900, 121, 121, 571, 1188, + /* 1680 */ 58, 58, 244, 1032, 122, 889, 452, 577, 452, 908, + /* 1690 */ 909, 1028, 300, 347, 504, 111, 263, 361, 165, 111, + /* 1700 */ 111, 1088, 452, 263, 974, 1153, 266, 1092, 986, 987, + /* 1710 */ 942, 939, 125, 125, 565, 1103, 872, 1103, 159, 941, + /* 1720 */ 1309, 125, 1557, 1028, 1028, 1030, 1031, 35, 542, 337, + /* 1730 */ 1530, 205, 1529, 541, 499, 1589, 490, 348, 1376, 352, + /* 1740 */ 355, 1032, 357, 1040, 359, 1324, 1308, 366, 563, 121, + /* 1750 */ 121, 376, 1188, 1389, 1434, 1362, 280, 122, 1374, 452, + /* 1760 */ 577, 452, 167, 1439, 1028, 1289, 1280, 1268, 1267, 1269, + /* 1770 */ 1609, 1359, 312, 313, 314, 397, 12, 237, 224, 1421, + /* 1780 */ 295, 1416, 1409, 1426, 339, 484, 340, 509, 1371, 1612, + /* 1790 */ 1372, 1425, 1244, 404, 301, 228, 1028, 1028, 1030, 1031, + /* 1800 */ 35, 1601, 1192, 454, 345, 1307, 292, 369, 1502, 1501, + /* 1810 */ 270, 396, 396, 395, 277, 393, 1370, 1369, 859, 1549, + /* 1820 */ 186, 123, 568, 235, 4, 1188, 391, 210, 211, 223, + /* 1830 */ 1547, 239, 1241, 327, 422, 96, 220, 195, 571, 180, + /* 1840 */ 188, 326, 468, 469, 190, 191, 502, 192, 193, 566, + /* 1850 */ 247, 109, 1430, 491, 199, 251, 102, 281, 402, 476, + /* 1860 */ 405, 1496, 452, 497, 253, 1422, 13, 1428, 14, 1427, + /* 1870 */ 203, 1507, 241, 500, 565, 354, 407, 92, 95, 1270, + /* 1880 */ 175, 254, 518, 43, 1327, 255, 1326, 1325, 436, 1518, + /* 1890 */ 350, 1318, 104, 229, 893, 1626, 440, 441, 1625, 408, + /* 1900 */ 240, 1296, 268, 1040, 310, 269, 1297, 527, 444, 121, + /* 1910 */ 121, 368, 1295, 1594, 1624, 311, 1394, 122, 1317, 452, + /* 1920 */ 577, 452, 374, 1580, 1028, 1393, 140, 553, 11, 90, + /* 1930 */ 568, 385, 4, 116, 318, 414, 1579, 110, 1483, 537, + /* 1940 */ 320, 567, 1350, 555, 42, 579, 571, 1349, 1198, 383, + /* 1950 */ 276, 390, 216, 389, 278, 279, 1028, 1028, 1030, 1031, + /* 1960 */ 35, 172, 580, 1265, 458, 1260, 415, 416, 185, 156, + /* 1970 */ 452, 1534, 1535, 173, 1533, 1532, 89, 308, 225, 226, + /* 1980 */ 846, 174, 565, 453, 217, 1188, 322, 236, 1102, 154, + /* 1990 */ 1100, 330, 187, 176, 1223, 243, 189, 925, 338, 246, + /* 2000 */ 1116, 194, 177, 425, 178, 427, 98, 196, 99, 100, + /* 2010 */ 101, 1040, 179, 1119, 1115, 248, 249, 121, 121, 163, + /* 2020 */ 24, 250, 349, 1238, 496, 122, 1108, 452, 577, 452, + /* 2030 */ 1192, 454, 1028, 266, 292, 200, 252, 201, 861, 396, + /* 2040 */ 396, 395, 277, 393, 15, 501, 859, 370, 292, 256, + /* 2050 */ 202, 554, 505, 396, 396, 395, 277, 393, 103, 239, + /* 2060 */ 859, 327, 25, 26, 1028, 1028, 1030, 1031, 35, 326, + /* 2070 */ 362, 510, 891, 239, 365, 327, 513, 904, 105, 309, + /* 2080 */ 164, 181, 27, 326, 106, 521, 107, 1185, 1069, 1155, + /* 2090 */ 17, 1154, 230, 1188, 284, 286, 265, 204, 125, 1171, + /* 2100 */ 241, 28, 978, 972, 29, 41, 1175, 1179, 175, 1173, + /* 2110 */ 30, 43, 31, 8, 241, 1178, 32, 1160, 208, 549, + /* 2120 */ 33, 111, 175, 1083, 1070, 43, 1068, 1072, 240, 113, + /* 2130 */ 114, 34, 561, 118, 1124, 271, 1073, 36, 18, 572, + /* 2140 */ 1033, 873, 240, 124, 37, 935, 272, 273, 1617, 183, + /* 2150 */ 153, 394, 1194, 1193, 1256, 1256, 1256, 1256, 1256, 1256, + /* 2160 */ 1256, 1256, 1256, 414, 1256, 1256, 1256, 1256, 320, 567, + /* 2170 */ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 414, 1256, 1256, + /* 2180 */ 1256, 1256, 320, 567, 1256, 1256, 1256, 1256, 1256, 1256, + /* 2190 */ 1256, 1256, 458, 1256, 1256, 1256, 1256, 1256, 1256, 1256, + /* 2200 */ 1256, 1256, 1256, 1256, 1256, 1256, 458, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 312, - /* 10 */ 195, 218, 195, 316, 195, 235, 254, 195, 256, 19, - /* 20 */ 297, 277, 278, 279, 218, 206, 213, 214, 206, 218, - /* 30 */ 219, 31, 206, 218, 219, 218, 219, 218, 219, 39, - /* 40 */ 218, 219, 195, 43, 44, 45, 195, 47, 48, 49, + /* 0 */ 277, 278, 279, 241, 242, 225, 195, 227, 195, 241, + /* 10 */ 242, 195, 217, 221, 195, 235, 254, 195, 256, 19, + /* 20 */ 225, 298, 254, 195, 256, 206, 213, 214, 206, 218, + /* 30 */ 219, 31, 206, 195, 218, 219, 195, 218, 219, 39, + /* 40 */ 218, 219, 313, 43, 44, 45, 317, 47, 48, 49, /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 19, - /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 195, - /* 70 */ 255, 237, 238, 254, 255, 256, 254, 255, 256, 264, - /* 80 */ 254, 207, 256, 43, 44, 45, 264, 47, 48, 49, - /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 251, - /* 100 */ 287, 253, 215, 103, 104, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 113, 114, 82, 265, 195, 271, 11, + /* 60 */ 241, 242, 195, 241, 242, 195, 255, 241, 242, 277, + /* 70 */ 278, 279, 234, 254, 255, 256, 254, 255, 256, 218, + /* 80 */ 254, 240, 256, 43, 44, 45, 264, 47, 48, 49, + /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 271, + /* 100 */ 287, 22, 23, 103, 104, 105, 106, 107, 108, 109, + /* 110 */ 110, 111, 112, 113, 114, 114, 47, 48, 49, 50, /* 120 */ 187, 188, 189, 190, 191, 192, 190, 87, 192, 89, - /* 130 */ 197, 19, 199, 197, 317, 199, 319, 25, 271, 206, - /* 140 */ 218, 219, 206, 103, 104, 105, 106, 107, 108, 109, + /* 130 */ 197, 19, 199, 197, 318, 199, 320, 25, 195, 206, + /* 140 */ 299, 271, 206, 103, 104, 105, 106, 107, 108, 109, /* 150 */ 110, 111, 112, 113, 114, 43, 44, 45, 195, 47, /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 170 */ 58, 60, 139, 140, 241, 242, 289, 241, 242, 309, - /* 180 */ 310, 294, 70, 47, 48, 49, 50, 254, 77, 256, - /* 190 */ 254, 195, 256, 55, 56, 57, 58, 59, 221, 88, - /* 200 */ 109, 90, 269, 240, 93, 269, 107, 108, 109, 110, - /* 210 */ 111, 112, 113, 114, 215, 103, 104, 105, 106, 107, - /* 220 */ 108, 109, 110, 111, 112, 113, 114, 136, 117, 118, - /* 230 */ 119, 298, 141, 300, 298, 19, 300, 129, 130, 317, - /* 240 */ 318, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 250 */ 112, 113, 114, 114, 277, 278, 279, 146, 122, 43, - /* 260 */ 44, 45, 195, 47, 48, 49, 50, 51, 52, 53, - /* 270 */ 54, 55, 56, 57, 58, 218, 277, 278, 279, 19, - /* 280 */ 19, 195, 286, 23, 68, 218, 219, 55, 56, 57, - /* 290 */ 58, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 300 */ 112, 113, 114, 43, 44, 45, 232, 47, 48, 49, - /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 103, + /* 170 */ 58, 60, 21, 195, 241, 242, 215, 241, 242, 312, + /* 180 */ 313, 102, 70, 205, 317, 207, 242, 254, 77, 256, + /* 190 */ 254, 122, 256, 55, 56, 57, 58, 59, 254, 88, + /* 200 */ 256, 90, 269, 240, 93, 269, 107, 108, 109, 110, + /* 210 */ 111, 112, 113, 114, 271, 103, 104, 105, 106, 107, + /* 220 */ 108, 109, 110, 111, 112, 113, 114, 313, 117, 118, + /* 230 */ 119, 317, 81, 195, 301, 19, 195, 301, 277, 278, + /* 240 */ 279, 103, 104, 105, 106, 107, 108, 109, 110, 111, + /* 250 */ 112, 113, 114, 55, 56, 57, 58, 146, 195, 43, + /* 260 */ 44, 45, 74, 47, 48, 49, 50, 51, 52, 53, + /* 270 */ 54, 55, 56, 57, 58, 124, 195, 60, 109, 110, + /* 280 */ 111, 112, 113, 114, 68, 195, 103, 104, 105, 106, + /* 290 */ 107, 108, 109, 110, 111, 112, 113, 114, 208, 218, + /* 300 */ 219, 103, 104, 105, 106, 107, 108, 109, 110, 111, + /* 310 */ 112, 113, 114, 162, 233, 24, 128, 129, 130, 103, /* 320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - /* 330 */ 114, 135, 60, 137, 138, 103, 104, 105, 106, 107, - /* 340 */ 108, 109, 110, 111, 112, 113, 114, 82, 281, 206, - /* 350 */ 195, 109, 110, 111, 112, 113, 114, 195, 195, 195, - /* 360 */ 205, 22, 207, 103, 104, 105, 106, 107, 108, 109, - /* 370 */ 110, 111, 112, 113, 114, 195, 60, 116, 117, 107, - /* 380 */ 108, 218, 219, 19, 241, 242, 121, 23, 116, 117, - /* 390 */ 118, 119, 306, 121, 308, 206, 234, 254, 15, 256, - /* 400 */ 195, 129, 259, 260, 139, 140, 145, 43, 44, 45, - /* 410 */ 200, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 420 */ 56, 57, 58, 218, 219, 60, 154, 19, 156, 265, - /* 430 */ 241, 242, 24, 117, 118, 119, 120, 21, 73, 123, - /* 440 */ 124, 125, 74, 254, 61, 256, 107, 108, 221, 133, - /* 450 */ 82, 43, 44, 45, 195, 47, 48, 49, 50, 51, - /* 460 */ 52, 53, 54, 55, 56, 57, 58, 103, 104, 105, - /* 470 */ 106, 107, 108, 109, 110, 111, 112, 113, 114, 195, - /* 480 */ 317, 318, 117, 118, 119, 22, 120, 195, 22, 123, - /* 490 */ 124, 125, 19, 20, 284, 22, 128, 81, 288, 133, - /* 500 */ 195, 195, 218, 219, 277, 278, 279, 139, 140, 36, - /* 510 */ 195, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 520 */ 112, 113, 114, 218, 219, 62, 60, 195, 241, 242, - /* 530 */ 271, 19, 240, 60, 189, 190, 191, 192, 233, 255, - /* 540 */ 124, 254, 197, 256, 199, 72, 129, 130, 264, 195, - /* 550 */ 195, 206, 22, 23, 60, 43, 44, 45, 206, 47, - /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 570 */ 58, 195, 218, 219, 101, 195, 60, 271, 162, 195, - /* 580 */ 107, 108, 109, 117, 118, 119, 241, 242, 115, 73, - /* 590 */ 117, 118, 119, 241, 242, 122, 60, 195, 266, 254, - /* 600 */ 312, 256, 218, 219, 316, 203, 254, 195, 256, 255, - /* 610 */ 208, 117, 118, 119, 269, 103, 104, 105, 106, 107, - /* 620 */ 108, 109, 110, 111, 112, 113, 114, 154, 155, 156, - /* 630 */ 157, 158, 102, 117, 118, 119, 19, 242, 144, 255, - /* 640 */ 23, 206, 24, 298, 195, 300, 206, 195, 264, 254, - /* 650 */ 206, 256, 240, 117, 118, 119, 183, 22, 22, 23, - /* 660 */ 43, 44, 45, 151, 47, 48, 49, 50, 51, 52, - /* 670 */ 53, 54, 55, 56, 57, 58, 241, 242, 60, 195, - /* 680 */ 19, 241, 242, 195, 23, 241, 242, 195, 152, 254, - /* 690 */ 310, 256, 243, 312, 254, 60, 256, 316, 254, 206, - /* 700 */ 256, 60, 218, 219, 43, 44, 45, 272, 47, 48, - /* 710 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 720 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 730 */ 113, 114, 240, 60, 241, 242, 118, 25, 102, 255, - /* 740 */ 166, 167, 101, 22, 26, 19, 20, 254, 22, 256, - /* 750 */ 139, 140, 117, 118, 119, 306, 195, 308, 117, 118, - /* 760 */ 237, 238, 36, 122, 103, 104, 105, 106, 107, 108, - /* 770 */ 109, 110, 111, 112, 113, 114, 195, 195, 60, 218, - /* 780 */ 219, 60, 109, 195, 19, 217, 60, 25, 23, 77, - /* 790 */ 117, 118, 119, 225, 233, 154, 155, 156, 72, 312, - /* 800 */ 218, 219, 90, 316, 22, 93, 303, 304, 43, 44, - /* 810 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, - /* 820 */ 55, 56, 57, 58, 183, 195, 195, 101, 19, 213, - /* 830 */ 214, 243, 23, 107, 108, 117, 118, 119, 117, 118, - /* 840 */ 119, 115, 60, 117, 118, 119, 195, 60, 122, 218, - /* 850 */ 219, 22, 43, 44, 45, 35, 47, 48, 49, 50, - /* 860 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104, - /* 870 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 880 */ 154, 155, 156, 157, 158, 195, 255, 67, 195, 60, - /* 890 */ 101, 240, 311, 312, 306, 75, 308, 316, 29, 117, - /* 900 */ 118, 119, 33, 287, 117, 118, 119, 118, 146, 183, - /* 910 */ 195, 122, 103, 104, 105, 106, 107, 108, 109, 110, - /* 920 */ 111, 112, 113, 114, 215, 195, 77, 60, 25, 195, - /* 930 */ 122, 144, 19, 218, 219, 66, 23, 88, 246, 90, - /* 940 */ 132, 25, 93, 154, 155, 156, 117, 118, 119, 257, - /* 950 */ 195, 131, 218, 219, 195, 265, 43, 44, 45, 195, - /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 970 */ 57, 58, 183, 218, 219, 195, 19, 218, 219, 195, - /* 980 */ 23, 195, 218, 219, 117, 118, 119, 195, 233, 255, - /* 990 */ 195, 195, 233, 22, 23, 146, 25, 233, 218, 219, - /* 1000 */ 43, 44, 45, 294, 47, 48, 49, 50, 51, 52, - /* 1010 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106, - /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 114, 195, 12, - /* 1030 */ 234, 195, 240, 74, 195, 255, 195, 60, 243, 262, - /* 1040 */ 263, 311, 312, 25, 27, 19, 316, 107, 108, 265, - /* 1050 */ 24, 265, 195, 150, 195, 139, 140, 218, 219, 42, - /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 1070 */ 113, 114, 233, 102, 67, 218, 219, 218, 219, 243, - /* 1080 */ 19, 64, 22, 23, 23, 25, 195, 128, 129, 130, - /* 1090 */ 233, 74, 233, 86, 154, 118, 156, 130, 265, 208, - /* 1100 */ 19, 306, 95, 308, 43, 44, 45, 266, 47, 48, - /* 1110 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1120 */ 153, 230, 96, 232, 43, 44, 45, 19, 47, 48, - /* 1130 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, - /* 1140 */ 114, 22, 306, 24, 308, 127, 120, 121, 122, 123, - /* 1150 */ 124, 125, 126, 195, 147, 212, 213, 214, 132, 23, - /* 1160 */ 195, 25, 102, 100, 103, 104, 105, 106, 107, 108, - /* 1170 */ 109, 110, 111, 112, 113, 114, 218, 219, 19, 60, - /* 1180 */ 195, 12, 210, 211, 103, 104, 105, 106, 107, 108, - /* 1190 */ 109, 110, 111, 112, 113, 114, 27, 134, 195, 195, - /* 1200 */ 195, 210, 211, 218, 219, 195, 47, 195, 212, 213, - /* 1210 */ 214, 42, 16, 130, 19, 112, 113, 114, 23, 77, - /* 1220 */ 195, 218, 219, 218, 219, 117, 163, 164, 218, 219, - /* 1230 */ 218, 219, 90, 64, 19, 93, 153, 118, 43, 44, - /* 1240 */ 45, 160, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1250 */ 55, 56, 57, 58, 195, 119, 272, 276, 43, 44, - /* 1260 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1270 */ 55, 56, 57, 58, 78, 116, 80, 218, 219, 116, - /* 1280 */ 144, 128, 129, 130, 218, 219, 61, 195, 47, 195, - /* 1290 */ 16, 132, 195, 263, 195, 314, 315, 267, 103, 104, - /* 1300 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 1310 */ 218, 219, 218, 219, 151, 218, 219, 195, 103, 104, - /* 1320 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - /* 1330 */ 210, 211, 195, 7, 8, 9, 195, 60, 195, 312, - /* 1340 */ 218, 219, 195, 316, 195, 120, 195, 263, 19, 195, - /* 1350 */ 125, 267, 78, 24, 80, 218, 219, 116, 162, 218, - /* 1360 */ 219, 218, 219, 301, 302, 218, 219, 195, 19, 218, - /* 1370 */ 219, 276, 43, 44, 45, 160, 47, 48, 49, 50, - /* 1380 */ 51, 52, 53, 54, 55, 56, 57, 58, 19, 146, - /* 1390 */ 218, 219, 43, 44, 45, 118, 47, 48, 49, 50, - /* 1400 */ 51, 52, 53, 54, 55, 56, 57, 58, 165, 314, - /* 1410 */ 315, 276, 43, 44, 45, 266, 47, 48, 49, 50, - /* 1420 */ 51, 52, 53, 54, 55, 56, 57, 58, 128, 129, - /* 1430 */ 130, 195, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1440 */ 111, 112, 113, 114, 195, 228, 195, 61, 195, 314, - /* 1450 */ 315, 25, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1460 */ 111, 112, 113, 114, 195, 22, 195, 218, 219, 218, - /* 1470 */ 219, 195, 103, 104, 105, 106, 107, 108, 109, 110, - /* 1480 */ 111, 112, 113, 114, 195, 195, 246, 218, 219, 218, - /* 1490 */ 219, 25, 19, 246, 218, 219, 246, 257, 259, 260, - /* 1500 */ 195, 22, 266, 60, 257, 195, 120, 257, 218, 219, - /* 1510 */ 116, 195, 19, 195, 150, 151, 25, 44, 45, 266, - /* 1520 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1530 */ 57, 58, 195, 54, 218, 219, 218, 219, 45, 145, - /* 1540 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 1550 */ 57, 58, 246, 121, 122, 218, 219, 19, 23, 31, - /* 1560 */ 25, 118, 159, 257, 161, 24, 195, 39, 195, 143, - /* 1570 */ 195, 19, 20, 22, 22, 24, 103, 104, 105, 106, - /* 1580 */ 107, 108, 109, 110, 111, 112, 113, 114, 36, 218, - /* 1590 */ 219, 218, 219, 218, 219, 195, 103, 104, 105, 106, - /* 1600 */ 107, 108, 109, 110, 111, 112, 113, 114, 195, 143, - /* 1610 */ 119, 136, 60, 195, 22, 195, 141, 195, 218, 219, - /* 1620 */ 195, 23, 195, 25, 72, 23, 131, 25, 195, 134, - /* 1630 */ 23, 218, 219, 195, 82, 144, 218, 219, 218, 219, - /* 1640 */ 218, 219, 195, 218, 219, 218, 219, 60, 23, 195, - /* 1650 */ 25, 218, 219, 101, 195, 117, 218, 219, 195, 107, - /* 1660 */ 108, 23, 195, 25, 195, 218, 219, 115, 228, 117, - /* 1670 */ 118, 119, 218, 219, 122, 195, 19, 218, 219, 195, - /* 1680 */ 60, 218, 219, 142, 195, 218, 219, 19, 20, 195, - /* 1690 */ 22, 139, 140, 23, 23, 25, 25, 195, 218, 219, - /* 1700 */ 7, 8, 218, 219, 36, 118, 154, 155, 156, 157, - /* 1710 */ 158, 195, 23, 195, 25, 84, 85, 49, 195, 23, - /* 1720 */ 195, 25, 195, 23, 195, 25, 195, 23, 60, 25, - /* 1730 */ 23, 23, 25, 25, 142, 183, 218, 219, 118, 195, - /* 1740 */ 72, 218, 219, 218, 219, 218, 219, 218, 219, 218, - /* 1750 */ 219, 195, 195, 146, 86, 98, 23, 195, 25, 91, - /* 1760 */ 19, 20, 154, 22, 156, 154, 23, 156, 25, 101, - /* 1770 */ 23, 195, 25, 195, 195, 107, 108, 36, 195, 195, - /* 1780 */ 195, 195, 228, 115, 195, 117, 118, 119, 195, 195, - /* 1790 */ 122, 261, 195, 321, 195, 195, 195, 258, 238, 195, - /* 1800 */ 195, 60, 299, 291, 195, 195, 258, 195, 195, 195, - /* 1810 */ 290, 244, 216, 72, 245, 193, 258, 258, 299, 258, - /* 1820 */ 299, 274, 154, 155, 156, 157, 158, 86, 247, 295, - /* 1830 */ 248, 295, 91, 19, 20, 270, 22, 274, 270, 248, - /* 1840 */ 274, 222, 101, 227, 274, 221, 231, 221, 107, 108, - /* 1850 */ 36, 183, 262, 247, 221, 283, 115, 262, 117, 118, - /* 1860 */ 119, 198, 116, 122, 220, 262, 61, 220, 220, 251, - /* 1870 */ 247, 142, 251, 245, 60, 202, 299, 202, 38, 262, - /* 1880 */ 202, 22, 152, 151, 296, 43, 72, 236, 18, 239, - /* 1890 */ 202, 239, 239, 239, 18, 154, 155, 156, 157, 158, - /* 1900 */ 86, 150, 201, 248, 275, 91, 248, 273, 236, 248, - /* 1910 */ 275, 275, 273, 236, 248, 101, 286, 202, 201, 159, - /* 1920 */ 63, 107, 108, 296, 183, 293, 202, 201, 22, 115, - /* 1930 */ 202, 117, 118, 119, 292, 223, 122, 201, 65, 202, - /* 1940 */ 201, 223, 220, 220, 22, 220, 226, 226, 229, 127, - /* 1950 */ 223, 220, 166, 24, 285, 220, 222, 114, 315, 285, - /* 1960 */ 220, 202, 220, 307, 92, 320, 320, 229, 154, 155, - /* 1970 */ 156, 157, 158, 0, 1, 2, 223, 83, 5, 268, - /* 1980 */ 149, 268, 146, 10, 11, 12, 13, 14, 22, 280, - /* 1990 */ 17, 202, 159, 19, 20, 251, 22, 183, 282, 148, - /* 2000 */ 252, 252, 250, 30, 249, 32, 248, 147, 25, 13, - /* 2010 */ 36, 204, 196, 40, 196, 6, 302, 194, 194, 194, - /* 2020 */ 209, 215, 209, 215, 215, 215, 224, 224, 216, 209, - /* 2030 */ 4, 216, 215, 3, 60, 22, 122, 19, 122, 19, - /* 2040 */ 125, 22, 15, 22, 71, 16, 72, 23, 23, 140, - /* 2050 */ 305, 152, 79, 25, 131, 82, 143, 20, 16, 305, - /* 2060 */ 1, 143, 145, 131, 131, 62, 54, 131, 37, 54, - /* 2070 */ 54, 152, 99, 117, 34, 101, 54, 24, 1, 5, - /* 2080 */ 22, 107, 108, 116, 76, 25, 162, 41, 142, 115, - /* 2090 */ 24, 117, 118, 119, 116, 20, 122, 19, 126, 23, - /* 2100 */ 132, 19, 20, 69, 22, 69, 22, 134, 22, 68, - /* 2110 */ 22, 22, 139, 140, 60, 141, 68, 24, 36, 28, - /* 2120 */ 97, 22, 37, 68, 23, 150, 34, 22, 154, 155, - /* 2130 */ 156, 157, 158, 23, 23, 22, 163, 25, 23, 142, - /* 2140 */ 23, 98, 60, 23, 22, 144, 25, 76, 34, 117, - /* 2150 */ 34, 89, 34, 34, 72, 87, 76, 183, 34, 94, - /* 2160 */ 34, 23, 22, 24, 34, 23, 25, 44, 25, 23, - /* 2170 */ 23, 23, 22, 22, 25, 11, 143, 25, 143, 23, - /* 2180 */ 22, 22, 22, 101, 23, 23, 136, 22, 25, 107, - /* 2190 */ 108, 142, 25, 142, 142, 23, 15, 115, 1, 117, - /* 2200 */ 118, 119, 1, 2, 122, 1, 5, 322, 322, 322, - /* 2210 */ 322, 10, 11, 12, 13, 14, 322, 322, 17, 322, - /* 2220 */ 5, 322, 322, 141, 322, 10, 11, 12, 13, 14, - /* 2230 */ 322, 30, 17, 32, 322, 322, 154, 155, 156, 157, - /* 2240 */ 158, 40, 322, 322, 322, 30, 322, 32, 322, 322, - /* 2250 */ 322, 322, 322, 322, 322, 40, 322, 322, 322, 322, - /* 2260 */ 322, 322, 322, 322, 322, 183, 322, 322, 322, 322, - /* 2270 */ 322, 322, 71, 322, 322, 322, 322, 322, 322, 322, - /* 2280 */ 79, 322, 322, 82, 322, 322, 71, 322, 322, 322, - /* 2290 */ 322, 322, 322, 322, 79, 322, 322, 82, 322, 322, - /* 2300 */ 99, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2310 */ 322, 322, 322, 322, 99, 322, 322, 322, 322, 322, - /* 2320 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2330 */ 322, 322, 322, 322, 322, 134, 322, 322, 322, 322, - /* 2340 */ 139, 140, 322, 322, 322, 322, 322, 322, 322, 134, - /* 2350 */ 322, 322, 322, 322, 139, 140, 322, 322, 322, 322, - /* 2360 */ 322, 322, 322, 322, 163, 322, 322, 322, 322, 322, - /* 2370 */ 322, 322, 322, 322, 322, 322, 322, 322, 163, 322, - /* 2380 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2390 */ 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, - /* 2400 */ 322, 322, 322, 322, 322, 322, 322, 322, 187, 187, - /* 2410 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2420 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2430 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2440 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2450 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2460 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2470 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2480 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2490 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2500 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2510 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2520 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2530 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2540 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2550 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, - /* 2560 */ 187, 187, 187, 187, 187, 187, + /* 330 */ 114, 195, 195, 215, 117, 118, 119, 120, 195, 19, + /* 340 */ 123, 124, 125, 207, 24, 74, 246, 60, 310, 311, + /* 350 */ 133, 60, 311, 82, 22, 218, 219, 257, 195, 19, + /* 360 */ 73, 218, 219, 43, 44, 45, 206, 47, 48, 49, + /* 370 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 22, + /* 380 */ 23, 218, 219, 43, 44, 45, 54, 47, 48, 49, + /* 390 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 128, + /* 400 */ 82, 241, 242, 195, 117, 118, 119, 289, 60, 118, + /* 410 */ 139, 140, 294, 195, 254, 195, 256, 195, 255, 259, + /* 420 */ 260, 73, 22, 103, 104, 105, 106, 107, 108, 109, + /* 430 */ 110, 111, 112, 113, 114, 206, 218, 219, 218, 219, + /* 440 */ 218, 219, 234, 103, 104, 105, 106, 107, 108, 109, + /* 450 */ 110, 111, 112, 113, 114, 318, 319, 139, 140, 102, + /* 460 */ 60, 318, 319, 221, 19, 117, 118, 119, 23, 195, + /* 470 */ 241, 242, 313, 255, 206, 255, 317, 255, 206, 129, + /* 480 */ 130, 206, 264, 254, 264, 256, 264, 195, 43, 44, + /* 490 */ 45, 151, 47, 48, 49, 50, 51, 52, 53, 54, + /* 500 */ 55, 56, 57, 58, 246, 213, 214, 19, 19, 241, + /* 510 */ 242, 195, 23, 241, 242, 257, 241, 242, 118, 277, + /* 520 */ 278, 279, 254, 29, 256, 60, 254, 33, 256, 254, + /* 530 */ 206, 256, 43, 44, 45, 218, 47, 48, 49, 50, + /* 540 */ 51, 52, 53, 54, 55, 56, 57, 58, 103, 104, + /* 550 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + /* 560 */ 66, 19, 218, 60, 120, 241, 242, 123, 124, 125, + /* 570 */ 60, 232, 77, 19, 20, 26, 22, 133, 254, 287, + /* 580 */ 256, 265, 117, 118, 119, 90, 312, 313, 93, 47, + /* 590 */ 36, 317, 103, 104, 105, 106, 107, 108, 109, 110, + /* 600 */ 111, 112, 113, 114, 116, 117, 277, 278, 279, 60, + /* 610 */ 107, 108, 19, 276, 60, 31, 23, 152, 195, 116, + /* 620 */ 117, 118, 119, 39, 121, 276, 72, 117, 118, 119, + /* 630 */ 166, 167, 129, 145, 237, 238, 43, 44, 45, 276, + /* 640 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 650 */ 57, 58, 315, 316, 144, 101, 19, 154, 116, 156, + /* 660 */ 23, 107, 108, 109, 315, 316, 117, 118, 119, 115, + /* 670 */ 60, 117, 118, 119, 132, 200, 122, 60, 315, 316, + /* 680 */ 43, 44, 45, 272, 47, 48, 49, 50, 51, 52, + /* 690 */ 53, 54, 55, 56, 57, 58, 103, 104, 105, 106, + /* 700 */ 107, 108, 109, 110, 111, 112, 113, 114, 154, 155, + /* 710 */ 156, 157, 158, 212, 213, 214, 22, 195, 101, 22, + /* 720 */ 60, 19, 20, 60, 22, 139, 140, 117, 118, 119, + /* 730 */ 22, 251, 195, 253, 117, 118, 195, 183, 36, 122, + /* 740 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 750 */ 113, 114, 195, 195, 60, 218, 219, 60, 195, 284, + /* 760 */ 19, 25, 60, 288, 23, 237, 238, 22, 60, 109, + /* 770 */ 233, 154, 155, 156, 72, 218, 219, 117, 118, 119, + /* 780 */ 117, 118, 119, 116, 43, 44, 45, 265, 47, 48, + /* 790 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 800 */ 183, 243, 25, 101, 19, 60, 265, 144, 23, 107, + /* 810 */ 108, 117, 118, 119, 117, 118, 119, 115, 151, 117, + /* 820 */ 118, 119, 82, 195, 122, 117, 118, 119, 43, 44, + /* 830 */ 45, 195, 47, 48, 49, 50, 51, 52, 53, 54, + /* 840 */ 55, 56, 57, 58, 103, 104, 105, 106, 107, 108, + /* 850 */ 109, 110, 111, 112, 113, 114, 154, 155, 156, 157, + /* 860 */ 158, 121, 117, 118, 119, 307, 101, 309, 195, 22, + /* 870 */ 23, 195, 25, 19, 35, 139, 140, 195, 24, 139, + /* 880 */ 140, 208, 195, 118, 109, 183, 22, 122, 103, 104, + /* 890 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + /* 900 */ 304, 305, 77, 230, 127, 232, 67, 195, 19, 195, + /* 910 */ 195, 136, 23, 88, 75, 90, 141, 203, 93, 154, + /* 920 */ 155, 156, 208, 295, 60, 243, 22, 23, 19, 25, + /* 930 */ 218, 219, 43, 44, 45, 100, 47, 48, 49, 50, + /* 940 */ 51, 52, 53, 54, 55, 56, 57, 58, 183, 102, + /* 950 */ 96, 195, 43, 44, 45, 240, 47, 48, 49, 50, + /* 960 */ 51, 52, 53, 54, 55, 56, 57, 58, 114, 134, + /* 970 */ 131, 146, 25, 286, 120, 121, 122, 123, 124, 125, + /* 980 */ 126, 117, 118, 119, 313, 195, 132, 195, 317, 307, + /* 990 */ 195, 309, 103, 104, 105, 106, 107, 108, 109, 110, + /* 1000 */ 111, 112, 113, 114, 195, 195, 102, 195, 195, 195, + /* 1010 */ 218, 219, 103, 104, 105, 106, 107, 108, 109, 110, + /* 1020 */ 111, 112, 113, 114, 77, 233, 195, 60, 218, 219, + /* 1030 */ 218, 219, 218, 219, 23, 195, 25, 90, 243, 159, + /* 1040 */ 93, 161, 19, 233, 195, 233, 23, 233, 16, 218, + /* 1050 */ 219, 195, 243, 212, 213, 214, 262, 263, 218, 219, + /* 1060 */ 195, 271, 19, 307, 233, 309, 43, 44, 45, 160, + /* 1070 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1080 */ 57, 58, 195, 218, 219, 118, 43, 44, 45, 240, + /* 1090 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1100 */ 57, 58, 307, 195, 309, 218, 219, 263, 12, 195, + /* 1110 */ 78, 267, 80, 112, 113, 114, 307, 22, 309, 24, + /* 1120 */ 255, 281, 266, 27, 107, 108, 103, 104, 105, 106, + /* 1130 */ 107, 108, 109, 110, 111, 112, 113, 114, 42, 195, + /* 1140 */ 11, 22, 255, 24, 195, 195, 103, 104, 105, 106, + /* 1150 */ 107, 108, 109, 110, 111, 112, 113, 114, 19, 195, + /* 1160 */ 64, 195, 218, 219, 195, 313, 195, 218, 219, 317, + /* 1170 */ 74, 154, 195, 156, 195, 195, 19, 233, 23, 60, + /* 1180 */ 25, 24, 218, 219, 218, 219, 195, 218, 219, 218, + /* 1190 */ 219, 128, 129, 130, 162, 263, 19, 218, 219, 267, + /* 1200 */ 43, 44, 45, 160, 47, 48, 49, 50, 51, 52, + /* 1210 */ 53, 54, 55, 56, 57, 58, 19, 240, 228, 255, + /* 1220 */ 43, 44, 45, 25, 47, 48, 49, 50, 51, 52, + /* 1230 */ 53, 54, 55, 56, 57, 58, 135, 118, 137, 138, + /* 1240 */ 43, 44, 45, 22, 47, 48, 49, 50, 51, 52, + /* 1250 */ 53, 54, 55, 56, 57, 58, 117, 266, 129, 130, + /* 1260 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1270 */ 113, 114, 195, 195, 119, 295, 195, 206, 195, 195, + /* 1280 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1290 */ 113, 114, 195, 195, 195, 218, 219, 195, 195, 144, + /* 1300 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1310 */ 113, 114, 241, 242, 67, 218, 219, 218, 219, 146, + /* 1320 */ 19, 218, 219, 240, 215, 254, 136, 256, 107, 108, + /* 1330 */ 195, 141, 255, 86, 128, 129, 130, 195, 165, 195, + /* 1340 */ 19, 143, 95, 272, 25, 44, 45, 266, 47, 48, + /* 1350 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 1360 */ 218, 219, 218, 219, 195, 12, 45, 195, 47, 48, + /* 1370 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* 1380 */ 27, 23, 7, 8, 9, 210, 211, 218, 219, 116, + /* 1390 */ 218, 219, 228, 16, 147, 42, 195, 295, 195, 19, + /* 1400 */ 20, 266, 22, 294, 103, 104, 105, 106, 107, 108, + /* 1410 */ 109, 110, 111, 112, 113, 114, 36, 64, 145, 218, + /* 1420 */ 219, 218, 219, 195, 103, 104, 105, 106, 107, 108, + /* 1430 */ 109, 110, 111, 112, 113, 114, 195, 154, 119, 156, + /* 1440 */ 60, 189, 190, 191, 192, 195, 218, 219, 195, 197, + /* 1450 */ 195, 199, 72, 195, 19, 78, 195, 80, 206, 218, + /* 1460 */ 219, 195, 82, 144, 210, 211, 195, 15, 218, 219, + /* 1470 */ 47, 218, 219, 218, 219, 259, 260, 195, 261, 218, + /* 1480 */ 219, 101, 302, 303, 218, 219, 195, 107, 108, 218, + /* 1490 */ 219, 150, 151, 241, 242, 115, 25, 117, 118, 119, + /* 1500 */ 218, 219, 122, 195, 146, 195, 254, 195, 256, 218, + /* 1510 */ 219, 246, 25, 61, 246, 19, 20, 195, 22, 139, + /* 1520 */ 140, 269, 257, 195, 266, 257, 218, 219, 218, 219, + /* 1530 */ 218, 219, 36, 246, 154, 155, 156, 157, 158, 116, + /* 1540 */ 218, 219, 195, 22, 257, 49, 218, 219, 23, 195, + /* 1550 */ 25, 195, 117, 301, 195, 25, 60, 195, 195, 23, + /* 1560 */ 195, 25, 195, 183, 24, 218, 219, 130, 72, 195, + /* 1570 */ 22, 195, 218, 219, 218, 219, 195, 218, 219, 195, + /* 1580 */ 218, 219, 86, 218, 219, 218, 219, 91, 19, 20, + /* 1590 */ 153, 22, 218, 219, 218, 219, 195, 101, 195, 218, + /* 1600 */ 219, 195, 195, 107, 108, 36, 23, 195, 25, 195, + /* 1610 */ 62, 115, 195, 117, 118, 119, 195, 146, 122, 218, + /* 1620 */ 219, 218, 219, 195, 218, 219, 19, 60, 122, 60, + /* 1630 */ 218, 219, 218, 219, 195, 218, 219, 150, 132, 218, + /* 1640 */ 219, 72, 195, 23, 195, 25, 218, 219, 195, 60, + /* 1650 */ 154, 155, 156, 157, 158, 86, 23, 195, 25, 195, + /* 1660 */ 91, 19, 20, 142, 22, 218, 219, 218, 219, 130, + /* 1670 */ 101, 218, 219, 143, 121, 122, 107, 108, 36, 183, + /* 1680 */ 218, 219, 142, 60, 115, 118, 117, 118, 119, 7, + /* 1690 */ 8, 122, 153, 23, 23, 25, 25, 23, 23, 25, + /* 1700 */ 25, 23, 60, 25, 23, 98, 25, 118, 84, 85, + /* 1710 */ 23, 23, 25, 25, 72, 154, 23, 156, 25, 23, + /* 1720 */ 228, 25, 195, 154, 155, 156, 157, 158, 86, 195, + /* 1730 */ 195, 258, 195, 91, 291, 322, 195, 195, 195, 195, + /* 1740 */ 195, 118, 195, 101, 195, 195, 195, 195, 238, 107, + /* 1750 */ 108, 195, 183, 195, 195, 195, 290, 115, 195, 117, + /* 1760 */ 118, 119, 244, 195, 122, 195, 195, 195, 195, 195, + /* 1770 */ 195, 258, 258, 258, 258, 193, 245, 300, 216, 274, + /* 1780 */ 247, 270, 270, 274, 296, 296, 248, 222, 262, 198, + /* 1790 */ 262, 274, 61, 274, 248, 231, 154, 155, 156, 157, + /* 1800 */ 158, 0, 1, 2, 247, 227, 5, 221, 221, 221, + /* 1810 */ 142, 10, 11, 12, 13, 14, 262, 262, 17, 202, + /* 1820 */ 300, 19, 20, 300, 22, 183, 247, 251, 251, 245, + /* 1830 */ 202, 30, 38, 32, 202, 152, 151, 22, 36, 43, + /* 1840 */ 236, 40, 18, 202, 239, 239, 18, 239, 239, 283, + /* 1850 */ 201, 150, 236, 202, 236, 201, 159, 202, 248, 248, + /* 1860 */ 248, 248, 60, 63, 201, 275, 273, 275, 273, 275, + /* 1870 */ 22, 286, 71, 223, 72, 202, 223, 297, 297, 202, + /* 1880 */ 79, 201, 116, 82, 220, 201, 220, 220, 65, 293, + /* 1890 */ 292, 229, 22, 166, 127, 226, 24, 114, 226, 223, + /* 1900 */ 99, 222, 202, 101, 285, 92, 220, 308, 83, 107, + /* 1910 */ 108, 220, 220, 316, 220, 285, 268, 115, 229, 117, + /* 1920 */ 118, 119, 223, 321, 122, 268, 149, 146, 22, 19, + /* 1930 */ 20, 202, 22, 159, 282, 134, 321, 148, 280, 147, + /* 1940 */ 139, 140, 252, 141, 25, 204, 36, 252, 13, 251, + /* 1950 */ 196, 248, 250, 249, 196, 6, 154, 155, 156, 157, + /* 1960 */ 158, 209, 194, 194, 163, 194, 306, 306, 303, 224, + /* 1970 */ 60, 215, 215, 209, 215, 215, 215, 224, 216, 216, + /* 1980 */ 4, 209, 72, 3, 22, 183, 164, 15, 23, 16, + /* 1990 */ 23, 140, 152, 131, 25, 24, 143, 20, 16, 145, + /* 2000 */ 1, 143, 131, 62, 131, 37, 54, 152, 54, 54, + /* 2010 */ 54, 101, 131, 117, 1, 34, 142, 107, 108, 5, + /* 2020 */ 22, 116, 162, 76, 41, 115, 69, 117, 118, 119, + /* 2030 */ 1, 2, 122, 25, 5, 69, 142, 116, 20, 10, + /* 2040 */ 11, 12, 13, 14, 24, 19, 17, 132, 5, 126, + /* 2050 */ 22, 141, 68, 10, 11, 12, 13, 14, 22, 30, + /* 2060 */ 17, 32, 22, 22, 154, 155, 156, 157, 158, 40, + /* 2070 */ 23, 68, 60, 30, 24, 32, 97, 28, 22, 68, + /* 2080 */ 23, 37, 34, 40, 150, 22, 25, 23, 23, 23, + /* 2090 */ 22, 98, 142, 183, 23, 23, 34, 22, 25, 89, + /* 2100 */ 71, 34, 117, 144, 34, 22, 76, 76, 79, 87, + /* 2110 */ 34, 82, 34, 44, 71, 94, 34, 23, 25, 24, + /* 2120 */ 34, 25, 79, 23, 23, 82, 23, 23, 99, 143, + /* 2130 */ 143, 22, 25, 25, 23, 22, 11, 22, 22, 25, + /* 2140 */ 23, 23, 99, 22, 22, 136, 142, 142, 142, 25, + /* 2150 */ 23, 15, 1, 1, 323, 323, 323, 323, 323, 323, + /* 2160 */ 323, 323, 323, 134, 323, 323, 323, 323, 139, 140, + /* 2170 */ 323, 323, 323, 323, 323, 323, 323, 134, 323, 323, + /* 2180 */ 323, 323, 139, 140, 323, 323, 323, 323, 323, 323, + /* 2190 */ 323, 323, 163, 323, 323, 323, 323, 323, 323, 323, + /* 2200 */ 323, 323, 323, 323, 323, 323, 163, 323, 323, 323, + /* 2210 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2220 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2230 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2240 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2250 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2260 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2270 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2280 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2290 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2300 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2310 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2320 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2330 */ 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, + /* 2340 */ 323, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2350 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2360 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2370 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2380 */ 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + /* 2390 */ 187, 187, 187, 187, }; -#define YY_SHIFT_COUNT (599) +#define YY_SHIFT_COUNT (582) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2215) +#define YY_SHIFT_MAX (2152) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 2201, 1973, 2215, 1552, 1552, 33, 368, 1668, 1741, 1814, - /* 10 */ 726, 726, 726, 265, 33, 33, 33, 33, 33, 0, - /* 20 */ 0, 216, 1349, 726, 726, 726, 726, 726, 726, 726, - /* 30 */ 726, 726, 726, 726, 726, 726, 726, 726, 272, 272, - /* 40 */ 111, 111, 316, 365, 516, 867, 867, 916, 916, 916, - /* 50 */ 916, 40, 112, 260, 364, 408, 512, 617, 661, 765, - /* 60 */ 809, 913, 957, 1061, 1081, 1195, 1215, 1329, 1349, 1349, - /* 70 */ 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, 1349, - /* 80 */ 1349, 1349, 1349, 1349, 1349, 1349, 1369, 1349, 1473, 1493, - /* 90 */ 1493, 473, 1974, 2082, 726, 726, 726, 726, 726, 726, - /* 100 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 110 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 120 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 130 */ 726, 726, 726, 726, 726, 726, 726, 726, 726, 726, - /* 140 */ 726, 726, 726, 726, 726, 726, 138, 232, 232, 232, - /* 150 */ 232, 232, 232, 232, 188, 99, 242, 718, 416, 1159, - /* 160 */ 867, 867, 940, 940, 867, 1103, 417, 574, 574, 574, - /* 170 */ 611, 139, 139, 2379, 2379, 1026, 1026, 1026, 536, 466, - /* 180 */ 466, 466, 466, 1017, 1017, 849, 718, 971, 1060, 867, - /* 190 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, - /* 200 */ 867, 867, 867, 867, 867, 867, 867, 867, 261, 712, - /* 210 */ 712, 867, 108, 1142, 1142, 977, 1108, 1108, 977, 977, - /* 220 */ 1243, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 641, 789, - /* 230 */ 789, 635, 366, 721, 673, 782, 494, 787, 829, 867, - /* 240 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, - /* 250 */ 959, 867, 867, 867, 867, 867, 867, 867, 867, 867, - /* 260 */ 867, 867, 867, 867, 867, 820, 820, 820, 867, 867, - /* 270 */ 867, 1136, 867, 867, 867, 1119, 1007, 867, 1169, 867, - /* 280 */ 867, 867, 867, 867, 867, 867, 867, 1225, 1153, 869, - /* 290 */ 196, 618, 618, 618, 618, 1491, 196, 196, 91, 339, - /* 300 */ 1326, 1386, 383, 1163, 1364, 1426, 1364, 1538, 903, 1163, - /* 310 */ 1163, 903, 1163, 1426, 1538, 1018, 1535, 1241, 1528, 1528, - /* 320 */ 1528, 1394, 1394, 1394, 1394, 762, 762, 1403, 1466, 1475, - /* 330 */ 1551, 1746, 1805, 1746, 1746, 1729, 1729, 1840, 1840, 1729, - /* 340 */ 1730, 1732, 1859, 1842, 1870, 1870, 1870, 1870, 1729, 1876, - /* 350 */ 1751, 1732, 1732, 1751, 1859, 1842, 1751, 1842, 1751, 1729, - /* 360 */ 1876, 1760, 1857, 1729, 1876, 1906, 1729, 1876, 1729, 1876, - /* 370 */ 1906, 1746, 1746, 1746, 1873, 1922, 1922, 1906, 1746, 1822, - /* 380 */ 1746, 1873, 1746, 1746, 1786, 1929, 1843, 1843, 1906, 1729, - /* 390 */ 1872, 1872, 1894, 1894, 1831, 1836, 1966, 1729, 1833, 1831, - /* 400 */ 1851, 1860, 1751, 1983, 1996, 1996, 2009, 2009, 2009, 2379, - /* 410 */ 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, 2379, - /* 420 */ 2379, 2379, 2379, 2379, 136, 1063, 1196, 530, 636, 1274, - /* 430 */ 1300, 1443, 1598, 1495, 1479, 967, 1083, 1602, 463, 1625, - /* 440 */ 1638, 1670, 1541, 1671, 1689, 1696, 1277, 1432, 1693, 808, - /* 450 */ 1700, 1607, 1657, 1587, 1704, 1707, 1631, 1708, 1733, 1608, - /* 460 */ 1611, 1743, 1747, 1620, 1592, 2026, 2030, 2013, 1914, 2018, - /* 470 */ 1916, 2020, 2019, 2021, 1915, 2027, 2029, 2024, 2025, 1909, - /* 480 */ 1899, 1923, 2028, 2028, 1913, 2037, 1917, 2042, 2059, 1918, - /* 490 */ 1932, 2028, 1933, 2003, 2031, 2028, 1919, 2012, 2015, 2016, - /* 500 */ 2022, 1936, 1956, 2040, 2053, 2077, 2074, 2058, 1967, 1924, - /* 510 */ 2034, 2060, 2036, 2008, 2046, 1946, 1978, 2066, 2075, 2078, - /* 520 */ 1968, 1972, 2084, 2041, 2086, 2088, 2076, 2089, 2048, 2054, - /* 530 */ 2093, 2023, 2091, 2099, 2055, 2085, 2101, 2092, 1975, 2105, - /* 540 */ 2110, 2111, 2112, 2115, 2113, 2043, 1997, 2117, 2120, 2032, - /* 550 */ 2114, 2122, 2001, 2121, 2116, 2118, 2119, 2124, 2062, 2071, - /* 560 */ 2068, 2123, 2080, 2065, 2126, 2138, 2140, 2139, 2141, 2143, - /* 570 */ 2130, 2033, 2035, 2142, 2121, 2146, 2147, 2148, 2150, 2149, - /* 580 */ 2152, 2156, 2151, 2164, 2158, 2159, 2161, 2162, 2160, 2165, - /* 590 */ 2163, 2050, 2049, 2051, 2052, 2167, 2172, 2181, 2197, 2204, + /* 0 */ 2029, 1801, 2043, 1380, 1380, 318, 271, 1496, 1569, 1642, + /* 10 */ 702, 702, 702, 740, 318, 318, 318, 318, 318, 0, + /* 20 */ 0, 216, 1177, 702, 702, 702, 702, 702, 702, 702, + /* 30 */ 702, 702, 702, 702, 702, 702, 702, 702, 503, 503, + /* 40 */ 111, 111, 217, 287, 348, 610, 610, 736, 736, 736, + /* 50 */ 736, 40, 112, 320, 340, 445, 489, 593, 637, 741, + /* 60 */ 785, 889, 909, 1023, 1043, 1157, 1177, 1177, 1177, 1177, + /* 70 */ 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, + /* 80 */ 1177, 1177, 1177, 1177, 1197, 1177, 1301, 1321, 1321, 554, + /* 90 */ 1802, 1910, 702, 702, 702, 702, 702, 702, 702, 702, + /* 100 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, + /* 110 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, + /* 120 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, + /* 130 */ 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, + /* 140 */ 702, 702, 138, 198, 198, 198, 198, 198, 198, 198, + /* 150 */ 183, 99, 169, 549, 610, 151, 542, 610, 610, 1017, + /* 160 */ 1017, 610, 1001, 350, 464, 464, 464, 586, 1, 1, + /* 170 */ 2207, 2207, 854, 854, 854, 465, 694, 694, 694, 694, + /* 180 */ 1096, 1096, 825, 549, 847, 904, 610, 610, 610, 610, + /* 190 */ 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, + /* 200 */ 610, 610, 610, 610, 610, 488, 947, 947, 610, 1129, + /* 210 */ 495, 495, 1139, 1139, 967, 967, 1173, 2207, 2207, 2207, + /* 220 */ 2207, 2207, 2207, 2207, 617, 765, 765, 697, 444, 708, + /* 230 */ 660, 745, 510, 663, 864, 610, 610, 610, 610, 610, + /* 240 */ 610, 610, 610, 610, 610, 188, 610, 610, 610, 610, + /* 250 */ 610, 610, 610, 610, 610, 610, 610, 610, 839, 839, + /* 260 */ 839, 610, 610, 610, 1155, 610, 610, 610, 1119, 1247, + /* 270 */ 610, 1353, 610, 610, 610, 610, 610, 610, 610, 610, + /* 280 */ 1063, 494, 1101, 291, 291, 291, 291, 1319, 1101, 1101, + /* 290 */ 775, 1221, 1375, 1452, 667, 1341, 1198, 1341, 1435, 1487, + /* 300 */ 667, 667, 1487, 667, 1198, 1435, 777, 1011, 1423, 584, + /* 310 */ 584, 584, 1273, 1273, 1273, 1273, 1471, 1471, 880, 1530, + /* 320 */ 1190, 1095, 1731, 1731, 1668, 1668, 1794, 1794, 1668, 1683, + /* 330 */ 1685, 1815, 1796, 1824, 1824, 1824, 1824, 1668, 1828, 1701, + /* 340 */ 1685, 1685, 1701, 1815, 1796, 1701, 1796, 1701, 1668, 1828, + /* 350 */ 1697, 1800, 1668, 1828, 1848, 1668, 1828, 1668, 1828, 1848, + /* 360 */ 1766, 1766, 1766, 1823, 1870, 1870, 1848, 1766, 1767, 1766, + /* 370 */ 1823, 1766, 1766, 1727, 1872, 1783, 1783, 1848, 1668, 1813, + /* 380 */ 1813, 1825, 1825, 1777, 1781, 1906, 1668, 1774, 1777, 1789, + /* 390 */ 1792, 1701, 1919, 1935, 1935, 1949, 1949, 1949, 2207, 2207, + /* 400 */ 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, 2207, + /* 410 */ 2207, 2207, 2207, 69, 1032, 79, 357, 1377, 1206, 400, + /* 420 */ 1525, 835, 332, 1540, 1437, 1539, 1536, 1548, 1583, 1620, + /* 430 */ 1633, 1670, 1671, 1674, 1567, 1553, 1682, 1506, 1675, 1358, + /* 440 */ 1607, 1589, 1678, 1681, 1624, 1687, 1688, 1283, 1561, 1693, + /* 450 */ 1696, 1623, 1521, 1976, 1980, 1962, 1822, 1972, 1973, 1965, + /* 460 */ 1967, 1851, 1840, 1862, 1969, 1969, 1971, 1853, 1977, 1854, + /* 470 */ 1982, 1999, 1858, 1871, 1969, 1873, 1941, 1968, 1969, 1855, + /* 480 */ 1952, 1954, 1955, 1956, 1881, 1896, 1981, 1874, 2013, 2014, + /* 490 */ 1998, 1905, 1860, 1957, 2008, 1966, 1947, 1983, 1894, 1921, + /* 500 */ 2020, 2018, 2026, 1915, 1923, 2028, 1984, 2036, 2040, 2047, + /* 510 */ 2041, 2003, 2012, 2050, 1979, 2049, 2056, 2011, 2044, 2057, + /* 520 */ 2048, 1934, 2063, 2064, 2065, 2061, 2066, 2068, 1993, 1950, + /* 530 */ 2071, 2072, 1985, 2062, 2075, 1959, 2073, 2067, 2070, 2076, + /* 540 */ 2078, 2010, 2030, 2022, 2069, 2031, 2021, 2082, 2094, 2083, + /* 550 */ 2095, 2093, 2096, 2086, 1986, 1987, 2100, 2073, 2101, 2103, + /* 560 */ 2104, 2109, 2107, 2108, 2111, 2113, 2125, 2115, 2116, 2117, + /* 570 */ 2118, 2121, 2122, 2114, 2009, 2004, 2005, 2006, 2124, 2127, + /* 580 */ 2136, 2151, 2152, }; -#define YY_REDUCE_COUNT (423) -#define YY_REDUCE_MIN (-303) -#define YY_REDUCE_MAX (1825) +#define YY_REDUCE_COUNT (412) +#define YY_REDUCE_MIN (-277) +#define YY_REDUCE_MAX (1772) static const short yy_reduce_ofst[] = { - /* 0 */ -67, 345, -64, -178, -181, 143, 435, -78, -183, 163, - /* 10 */ -185, 284, 384, -174, 189, 352, 440, 444, 493, -23, - /* 20 */ 227, -277, -1, 305, 561, 755, 759, 764, -189, 839, - /* 30 */ 857, 354, 484, 859, 631, 67, 734, 780, -187, 616, - /* 40 */ 581, 730, 891, 449, 588, 795, 836, -238, 287, -238, - /* 50 */ 287, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 60 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 70 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 80 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256, - /* 90 */ -256, 205, 582, 715, 958, 985, 1003, 1005, 1010, 1012, - /* 100 */ 1059, 1066, 1092, 1094, 1097, 1122, 1137, 1141, 1143, 1147, - /* 110 */ 1151, 1172, 1249, 1251, 1269, 1271, 1276, 1290, 1316, 1318, - /* 120 */ 1337, 1371, 1373, 1375, 1400, 1413, 1418, 1420, 1422, 1425, - /* 130 */ 1427, 1433, 1438, 1447, 1454, 1459, 1463, 1467, 1480, 1484, - /* 140 */ 1518, 1523, 1525, 1527, 1529, 1531, -256, -256, -256, -256, - /* 150 */ -256, -256, -256, -256, -256, -256, -256, 155, 210, -220, - /* 160 */ 86, -130, 943, 996, 402, -256, -113, 981, 1095, 1135, - /* 170 */ 395, -256, -256, -256, -256, 568, 568, 568, -4, -153, - /* 180 */ -133, 259, 306, -166, 523, -303, -126, 503, 503, -37, - /* 190 */ -149, 164, 690, 292, 412, 492, 651, 784, 332, 786, - /* 200 */ 841, 1149, 833, 1236, 792, 162, 796, 1253, 777, 288, - /* 210 */ 381, 380, 709, 487, 1027, 972, 1030, 1084, 991, 1120, - /* 220 */ -152, 1062, 692, 1240, 1247, 1250, 1239, 1306, -207, -194, - /* 230 */ 57, 180, 74, 315, 355, 376, 452, 488, 630, 693, - /* 240 */ 965, 1004, 1025, 1099, 1154, 1289, 1305, 1310, 1469, 1489, - /* 250 */ 984, 1494, 1502, 1516, 1544, 1556, 1557, 1562, 1576, 1578, - /* 260 */ 1579, 1583, 1584, 1585, 1586, 1217, 1440, 1554, 1589, 1593, - /* 270 */ 1594, 1530, 1597, 1599, 1600, 1539, 1472, 1601, 1560, 1604, - /* 280 */ 355, 1605, 1609, 1610, 1612, 1613, 1614, 1503, 1512, 1520, - /* 290 */ 1567, 1548, 1558, 1559, 1561, 1530, 1567, 1567, 1569, 1596, - /* 300 */ 1622, 1519, 1521, 1547, 1565, 1581, 1568, 1534, 1582, 1563, - /* 310 */ 1566, 1591, 1570, 1606, 1536, 1619, 1615, 1616, 1624, 1626, - /* 320 */ 1633, 1590, 1595, 1603, 1617, 1618, 1621, 1572, 1623, 1628, - /* 330 */ 1663, 1644, 1577, 1647, 1648, 1673, 1675, 1588, 1627, 1678, - /* 340 */ 1630, 1629, 1634, 1651, 1650, 1652, 1653, 1654, 1688, 1701, - /* 350 */ 1655, 1635, 1636, 1658, 1639, 1672, 1661, 1677, 1666, 1715, - /* 360 */ 1717, 1632, 1642, 1724, 1726, 1712, 1728, 1736, 1737, 1739, - /* 370 */ 1718, 1722, 1723, 1725, 1719, 1720, 1721, 1727, 1731, 1734, - /* 380 */ 1735, 1738, 1740, 1742, 1643, 1656, 1669, 1674, 1753, 1759, - /* 390 */ 1645, 1646, 1711, 1713, 1748, 1744, 1709, 1789, 1716, 1749, - /* 400 */ 1752, 1755, 1758, 1807, 1816, 1818, 1823, 1824, 1825, 1745, - /* 410 */ 1754, 1714, 1811, 1806, 1808, 1809, 1810, 1813, 1802, 1803, - /* 420 */ 1812, 1815, 1817, 1820, + /* 0 */ -67, 1252, -64, -178, -181, 160, 1071, 143, -184, 137, + /* 10 */ 218, 220, 222, -174, 229, 268, 272, 275, 324, -208, + /* 20 */ 242, -277, -39, 81, 537, 792, 810, 812, -189, 814, + /* 30 */ 831, 163, 865, 944, 887, 840, 964, 1077, -187, 292, + /* 40 */ -133, 274, 673, 558, 682, 795, 809, -238, -232, -238, + /* 50 */ -232, 329, 329, 329, 329, 329, 329, 329, 329, 329, + /* 60 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + /* 70 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, + /* 80 */ 329, 329, 329, 329, 329, 329, 329, 329, 329, 557, + /* 90 */ 712, 949, 966, 969, 971, 979, 1097, 1099, 1103, 1142, + /* 100 */ 1144, 1169, 1172, 1201, 1203, 1228, 1241, 1250, 1253, 1255, + /* 110 */ 1261, 1266, 1271, 1282, 1291, 1308, 1310, 1312, 1322, 1328, + /* 120 */ 1347, 1354, 1356, 1359, 1362, 1365, 1367, 1374, 1376, 1381, + /* 130 */ 1401, 1403, 1406, 1412, 1414, 1417, 1421, 1428, 1447, 1449, + /* 140 */ 1453, 1462, 329, 329, 329, 329, 329, 329, 329, 329, + /* 150 */ 329, 329, 329, -22, -159, 475, -220, 756, 38, 501, + /* 160 */ 841, 714, 329, 118, 337, 349, 363, -56, 329, 329, + /* 170 */ 329, 329, -205, -205, -205, 687, -172, -130, -57, 790, + /* 180 */ 397, 528, -271, 136, 596, 596, 90, 316, 522, 541, + /* 190 */ -37, 715, 849, 977, 628, 856, 980, 991, 1081, 1102, + /* 200 */ 1135, 1083, -162, 208, 1258, 794, -86, 159, 41, 1109, + /* 210 */ 671, 852, 844, 932, 1175, 1254, 480, 1180, 100, 258, + /* 220 */ 1265, 1268, 1216, 1287, -139, 317, 344, 63, 339, 423, + /* 230 */ 563, 636, 676, 813, 908, 914, 950, 1078, 1084, 1098, + /* 240 */ 1363, 1384, 1407, 1439, 1464, 411, 1527, 1534, 1535, 1537, + /* 250 */ 1541, 1542, 1543, 1544, 1545, 1547, 1549, 1550, 990, 1164, + /* 260 */ 1492, 1551, 1552, 1556, 1217, 1558, 1559, 1560, 1473, 1413, + /* 270 */ 1563, 1510, 1568, 563, 1570, 1571, 1572, 1573, 1574, 1575, + /* 280 */ 1443, 1466, 1518, 1513, 1514, 1515, 1516, 1217, 1518, 1518, + /* 290 */ 1531, 1562, 1582, 1477, 1505, 1511, 1533, 1512, 1488, 1538, + /* 300 */ 1509, 1517, 1546, 1519, 1557, 1489, 1565, 1564, 1578, 1586, + /* 310 */ 1587, 1588, 1526, 1528, 1554, 1555, 1576, 1577, 1566, 1579, + /* 320 */ 1584, 1591, 1520, 1523, 1617, 1628, 1580, 1581, 1632, 1585, + /* 330 */ 1590, 1593, 1604, 1605, 1606, 1608, 1609, 1641, 1649, 1610, + /* 340 */ 1592, 1594, 1611, 1595, 1616, 1612, 1618, 1613, 1651, 1654, + /* 350 */ 1596, 1598, 1655, 1663, 1650, 1673, 1680, 1677, 1684, 1653, + /* 360 */ 1664, 1666, 1667, 1662, 1669, 1672, 1676, 1686, 1679, 1691, + /* 370 */ 1689, 1692, 1694, 1597, 1599, 1619, 1630, 1699, 1700, 1602, + /* 380 */ 1615, 1648, 1657, 1690, 1698, 1658, 1729, 1652, 1695, 1702, + /* 390 */ 1704, 1703, 1741, 1754, 1758, 1768, 1769, 1771, 1660, 1661, + /* 400 */ 1665, 1752, 1756, 1757, 1759, 1760, 1764, 1745, 1753, 1762, + /* 410 */ 1763, 1761, 1772, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1691, 1691, 1691, 1516, 1279, 1392, 1279, 1279, 1279, 1279, - /* 10 */ 1516, 1516, 1516, 1279, 1279, 1279, 1279, 1279, 1279, 1422, - /* 20 */ 1422, 1568, 1312, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 30 */ 1279, 1279, 1279, 1279, 1279, 1515, 1279, 1279, 1279, 1279, - /* 40 */ 1607, 1607, 1279, 1279, 1279, 1279, 1279, 1592, 1591, 1279, - /* 50 */ 1279, 1279, 1431, 1279, 1279, 1279, 1438, 1279, 1279, 1279, - /* 60 */ 1279, 1279, 1517, 1518, 1279, 1279, 1279, 1279, 1567, 1569, - /* 70 */ 1533, 1445, 1444, 1443, 1442, 1551, 1410, 1436, 1429, 1433, - /* 80 */ 1512, 1513, 1511, 1670, 1518, 1517, 1279, 1432, 1480, 1496, - /* 90 */ 1479, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 100 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 110 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 120 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 130 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 140 */ 1279, 1279, 1279, 1279, 1279, 1279, 1488, 1495, 1494, 1493, - /* 150 */ 1502, 1492, 1489, 1482, 1481, 1483, 1484, 1303, 1300, 1354, - /* 160 */ 1279, 1279, 1279, 1279, 1279, 1485, 1312, 1473, 1472, 1471, - /* 170 */ 1279, 1499, 1486, 1498, 1497, 1575, 1644, 1643, 1534, 1279, - /* 180 */ 1279, 1279, 1279, 1279, 1279, 1607, 1279, 1279, 1279, 1279, - /* 190 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 200 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1412, 1607, - /* 210 */ 1607, 1279, 1312, 1607, 1607, 1308, 1413, 1413, 1308, 1308, - /* 220 */ 1416, 1587, 1383, 1383, 1383, 1383, 1392, 1383, 1279, 1279, - /* 230 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 240 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1572, 1570, 1279, - /* 250 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 260 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 270 */ 1279, 1279, 1279, 1279, 1279, 1388, 1279, 1279, 1279, 1279, - /* 280 */ 1279, 1279, 1279, 1279, 1279, 1279, 1637, 1683, 1279, 1546, - /* 290 */ 1368, 1388, 1388, 1388, 1388, 1390, 1369, 1367, 1382, 1313, - /* 300 */ 1286, 1683, 1683, 1448, 1437, 1389, 1437, 1680, 1435, 1448, - /* 310 */ 1448, 1435, 1448, 1389, 1680, 1329, 1659, 1324, 1422, 1422, - /* 320 */ 1422, 1412, 1412, 1412, 1412, 1416, 1416, 1514, 1389, 1382, - /* 330 */ 1279, 1355, 1683, 1355, 1355, 1398, 1398, 1682, 1682, 1398, - /* 340 */ 1534, 1667, 1457, 1357, 1363, 1363, 1363, 1363, 1398, 1297, - /* 350 */ 1435, 1667, 1667, 1435, 1457, 1357, 1435, 1357, 1435, 1398, - /* 360 */ 1297, 1550, 1678, 1398, 1297, 1524, 1398, 1297, 1398, 1297, - /* 370 */ 1524, 1355, 1355, 1355, 1344, 1279, 1279, 1524, 1355, 1329, - /* 380 */ 1355, 1344, 1355, 1355, 1625, 1279, 1528, 1528, 1524, 1398, - /* 390 */ 1617, 1617, 1425, 1425, 1430, 1416, 1519, 1398, 1279, 1430, - /* 400 */ 1428, 1426, 1435, 1347, 1640, 1640, 1636, 1636, 1636, 1688, - /* 410 */ 1688, 1587, 1652, 1312, 1312, 1312, 1312, 1652, 1331, 1331, - /* 420 */ 1313, 1313, 1312, 1652, 1279, 1279, 1279, 1279, 1279, 1279, - /* 430 */ 1279, 1647, 1279, 1279, 1535, 1279, 1279, 1279, 1279, 1279, - /* 440 */ 1279, 1279, 1402, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 450 */ 1279, 1279, 1593, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 460 */ 1279, 1279, 1279, 1279, 1462, 1279, 1282, 1584, 1279, 1279, - /* 470 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 480 */ 1279, 1279, 1439, 1440, 1279, 1279, 1279, 1279, 1279, 1279, - /* 490 */ 1279, 1454, 1279, 1279, 1279, 1449, 1279, 1279, 1279, 1279, - /* 500 */ 1279, 1279, 1279, 1279, 1403, 1279, 1279, 1279, 1279, 1279, - /* 510 */ 1279, 1549, 1548, 1279, 1279, 1400, 1279, 1279, 1279, 1279, - /* 520 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1327, - /* 530 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 540 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 550 */ 1279, 1279, 1279, 1427, 1279, 1279, 1279, 1279, 1279, 1279, - /* 560 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1622, 1417, - /* 570 */ 1279, 1279, 1279, 1279, 1671, 1279, 1279, 1279, 1279, 1377, - /* 580 */ 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, 1279, - /* 590 */ 1663, 1371, 1463, 1279, 1466, 1301, 1279, 1291, 1279, 1279, + /* 0 */ 1663, 1663, 1663, 1491, 1254, 1367, 1254, 1254, 1254, 1254, + /* 10 */ 1491, 1491, 1491, 1254, 1254, 1254, 1254, 1254, 1254, 1397, + /* 20 */ 1397, 1544, 1287, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 30 */ 1254, 1254, 1254, 1254, 1254, 1490, 1254, 1254, 1254, 1254, + /* 40 */ 1578, 1578, 1254, 1254, 1254, 1254, 1254, 1563, 1562, 1254, + /* 50 */ 1254, 1254, 1406, 1254, 1413, 1254, 1254, 1254, 1254, 1254, + /* 60 */ 1492, 1493, 1254, 1254, 1254, 1254, 1543, 1545, 1508, 1420, + /* 70 */ 1419, 1418, 1417, 1526, 1385, 1411, 1404, 1408, 1487, 1488, + /* 80 */ 1486, 1641, 1493, 1492, 1254, 1407, 1455, 1471, 1454, 1254, + /* 90 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 100 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 110 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 120 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 130 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 140 */ 1254, 1254, 1463, 1470, 1469, 1468, 1477, 1467, 1464, 1457, + /* 150 */ 1456, 1458, 1459, 1278, 1254, 1275, 1329, 1254, 1254, 1254, + /* 160 */ 1254, 1254, 1460, 1287, 1448, 1447, 1446, 1254, 1474, 1461, + /* 170 */ 1473, 1472, 1551, 1615, 1614, 1509, 1254, 1254, 1254, 1254, + /* 180 */ 1254, 1254, 1578, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 190 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 200 */ 1254, 1254, 1254, 1254, 1254, 1387, 1578, 1578, 1254, 1287, + /* 210 */ 1578, 1578, 1388, 1388, 1283, 1283, 1391, 1558, 1358, 1358, + /* 220 */ 1358, 1358, 1367, 1358, 1254, 1254, 1254, 1254, 1254, 1254, + /* 230 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1548, + /* 240 */ 1546, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 250 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 260 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1363, 1254, + /* 270 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1608, + /* 280 */ 1254, 1521, 1343, 1363, 1363, 1363, 1363, 1365, 1344, 1342, + /* 290 */ 1357, 1288, 1261, 1655, 1423, 1412, 1364, 1412, 1652, 1410, + /* 300 */ 1423, 1423, 1410, 1423, 1364, 1652, 1304, 1630, 1299, 1397, + /* 310 */ 1397, 1397, 1387, 1387, 1387, 1387, 1391, 1391, 1489, 1364, + /* 320 */ 1357, 1254, 1655, 1655, 1373, 1373, 1654, 1654, 1373, 1509, + /* 330 */ 1638, 1432, 1332, 1338, 1338, 1338, 1338, 1373, 1272, 1410, + /* 340 */ 1638, 1638, 1410, 1432, 1332, 1410, 1332, 1410, 1373, 1272, + /* 350 */ 1525, 1649, 1373, 1272, 1499, 1373, 1272, 1373, 1272, 1499, + /* 360 */ 1330, 1330, 1330, 1319, 1254, 1254, 1499, 1330, 1304, 1330, + /* 370 */ 1319, 1330, 1330, 1596, 1254, 1503, 1503, 1499, 1373, 1588, + /* 380 */ 1588, 1400, 1400, 1405, 1391, 1494, 1373, 1254, 1405, 1403, + /* 390 */ 1401, 1410, 1322, 1611, 1611, 1607, 1607, 1607, 1660, 1660, + /* 400 */ 1558, 1623, 1287, 1287, 1287, 1287, 1623, 1306, 1306, 1288, + /* 410 */ 1288, 1287, 1623, 1254, 1254, 1254, 1254, 1254, 1254, 1618, + /* 420 */ 1254, 1553, 1510, 1377, 1254, 1254, 1254, 1254, 1254, 1254, + /* 430 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 440 */ 1564, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 450 */ 1254, 1254, 1437, 1254, 1257, 1555, 1254, 1254, 1254, 1254, + /* 460 */ 1254, 1254, 1254, 1254, 1414, 1415, 1378, 1254, 1254, 1254, + /* 470 */ 1254, 1254, 1254, 1254, 1429, 1254, 1254, 1254, 1424, 1254, + /* 480 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1651, 1254, 1254, + /* 490 */ 1254, 1254, 1254, 1254, 1524, 1523, 1254, 1254, 1375, 1254, + /* 500 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 510 */ 1254, 1254, 1302, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 520 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 530 */ 1254, 1254, 1254, 1254, 1254, 1254, 1402, 1254, 1254, 1254, + /* 540 */ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 550 */ 1254, 1593, 1392, 1254, 1254, 1254, 1254, 1642, 1254, 1254, + /* 560 */ 1254, 1254, 1352, 1254, 1254, 1254, 1254, 1254, 1254, 1254, + /* 570 */ 1254, 1254, 1254, 1634, 1346, 1438, 1254, 1441, 1276, 1254, + /* 580 */ 1266, 1254, 1254, }; /********** End of lemon-generated parsing tables *****************************/ @@ -180661,33 +179401,34 @@ static const char *const yyTokenName[] = { /* 292 */ "foreach_clause", /* 293 */ "when_clause", /* 294 */ "trigger_cmd", - /* 295 */ "tridxby", - /* 296 */ "database_kw_opt", - /* 297 */ "key_opt", - /* 298 */ "alter_add", - /* 299 */ "kwcolumn_opt", - /* 300 */ "create_vtab", - /* 301 */ "vtabarglist", - /* 302 */ "vtabarg", - /* 303 */ "vtabargtoken", - /* 304 */ "lp", - /* 305 */ "anylist", - /* 306 */ "wqitem", - /* 307 */ "wqas", - /* 308 */ "withnm", - /* 309 */ "windowdefn_list", - /* 310 */ "windowdefn", - /* 311 */ "window", - /* 312 */ "frame_opt", - /* 313 */ "part_opt", - /* 314 */ "filter_clause", - /* 315 */ "over_clause", - /* 316 */ "range_or_rows", - /* 317 */ "frame_bound", - /* 318 */ "frame_bound_s", - /* 319 */ "frame_bound_e", - /* 320 */ "frame_exclude_opt", - /* 321 */ "frame_exclude", + /* 295 */ "trnm", + /* 296 */ "tridxby", + /* 297 */ "database_kw_opt", + /* 298 */ "key_opt", + /* 299 */ "add_column_fullname", + /* 300 */ "kwcolumn_opt", + /* 301 */ "create_vtab", + /* 302 */ "vtabarglist", + /* 303 */ "vtabarg", + /* 304 */ "vtabargtoken", + /* 305 */ "lp", + /* 306 */ "anylist", + /* 307 */ "wqitem", + /* 308 */ "wqas", + /* 309 */ "withnm", + /* 310 */ "windowdefn_list", + /* 311 */ "windowdefn", + /* 312 */ "window", + /* 313 */ "frame_opt", + /* 314 */ "part_opt", + /* 315 */ "filter_clause", + /* 316 */ "over_clause", + /* 317 */ "range_or_rows", + /* 318 */ "frame_bound", + /* 319 */ "frame_bound_s", + /* 320 */ "frame_bound_e", + /* 321 */ "frame_exclude_opt", + /* 322 */ "frame_exclude", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -180817,8 +179558,8 @@ static const char *const yyRuleName[] = { /* 119 */ "fullname ::= nm DOT nm", /* 120 */ "xfullname ::= nm", /* 121 */ "xfullname ::= nm DOT nm", - /* 122 */ "xfullname ::= nm AS nm", - /* 123 */ "xfullname ::= nm DOT nm AS nm", + /* 122 */ "xfullname ::= nm DOT nm AS nm", + /* 123 */ "xfullname ::= nm AS nm", /* 124 */ "joinop ::= COMMA|JOIN", /* 125 */ "joinop ::= JOIN_KW JOIN", /* 126 */ "joinop ::= JOIN_KW nm JOIN", @@ -180967,146 +179708,143 @@ static const char *const yyRuleName[] = { /* 269 */ "when_clause ::= WHEN expr", /* 270 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", /* 271 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 272 */ "tridxby ::= INDEXED BY nm", - /* 273 */ "tridxby ::= NOT INDEXED", - /* 274 */ "trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt", - /* 275 */ "trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt", - /* 276 */ "trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt", - /* 277 */ "trigger_cmd ::= scanpt select scanpt", - /* 278 */ "expr ::= RAISE LP IGNORE RP", - /* 279 */ "expr ::= RAISE LP raisetype COMMA expr RP", - /* 280 */ "raisetype ::= ROLLBACK", - /* 281 */ "raisetype ::= ABORT", - /* 282 */ "raisetype ::= FAIL", - /* 283 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 284 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 285 */ "cmd ::= DETACH database_kw_opt expr", - /* 286 */ "key_opt ::=", - /* 287 */ "key_opt ::= KEY expr", - /* 288 */ "cmd ::= REINDEX", - /* 289 */ "cmd ::= REINDEX nm dbnm", - /* 290 */ "cmd ::= ANALYZE", - /* 291 */ "cmd ::= ANALYZE nm dbnm", - /* 292 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 293 */ "cmd ::= alter_add carglist", - /* 294 */ "alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken", + /* 272 */ "trnm ::= nm DOT nm", + /* 273 */ "tridxby ::= INDEXED BY nm", + /* 274 */ "tridxby ::= NOT INDEXED", + /* 275 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", + /* 276 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", + /* 277 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", + /* 278 */ "trigger_cmd ::= scanpt select scanpt", + /* 279 */ "expr ::= RAISE LP IGNORE RP", + /* 280 */ "expr ::= RAISE LP raisetype COMMA expr RP", + /* 281 */ "raisetype ::= ROLLBACK", + /* 282 */ "raisetype ::= ABORT", + /* 283 */ "raisetype ::= FAIL", + /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 286 */ "cmd ::= DETACH database_kw_opt expr", + /* 287 */ "key_opt ::=", + /* 288 */ "key_opt ::= KEY expr", + /* 289 */ "cmd ::= REINDEX", + /* 290 */ "cmd ::= REINDEX nm dbnm", + /* 291 */ "cmd ::= ANALYZE", + /* 292 */ "cmd ::= ANALYZE nm dbnm", + /* 293 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 294 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", /* 295 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 296 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 297 */ "cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm", - /* 298 */ "cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL", - /* 299 */ "cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf", - /* 300 */ "cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf", - /* 301 */ "cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf", - /* 302 */ "cmd ::= create_vtab", - /* 303 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 304 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 305 */ "vtabarg ::=", - /* 306 */ "vtabargtoken ::= ANY", - /* 307 */ "vtabargtoken ::= lp anylist RP", - /* 308 */ "lp ::= LP", - /* 309 */ "with ::= WITH wqlist", - /* 310 */ "with ::= WITH RECURSIVE wqlist", - /* 311 */ "wqas ::= AS", - /* 312 */ "wqas ::= AS MATERIALIZED", - /* 313 */ "wqas ::= AS NOT MATERIALIZED", - /* 314 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", - /* 315 */ "withnm ::= nm", - /* 316 */ "wqlist ::= wqitem", - /* 317 */ "wqlist ::= wqlist COMMA wqitem", - /* 318 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 319 */ "windowdefn ::= nm AS LP window RP", - /* 320 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 321 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 322 */ "window ::= ORDER BY sortlist frame_opt", - /* 323 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 324 */ "window ::= nm frame_opt", - /* 325 */ "frame_opt ::=", - /* 326 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 327 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 328 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 329 */ "frame_bound_s ::= frame_bound", - /* 330 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 331 */ "frame_bound_e ::= frame_bound", - /* 332 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 333 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 334 */ "frame_bound ::= CURRENT ROW", - /* 335 */ "frame_exclude_opt ::=", - /* 336 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 337 */ "frame_exclude ::= NO OTHERS", - /* 338 */ "frame_exclude ::= CURRENT ROW", - /* 339 */ "frame_exclude ::= GROUP|TIES", - /* 340 */ "window_clause ::= WINDOW windowdefn_list", - /* 341 */ "filter_over ::= filter_clause over_clause", - /* 342 */ "filter_over ::= over_clause", - /* 343 */ "filter_over ::= filter_clause", - /* 344 */ "over_clause ::= OVER LP window RP", - /* 345 */ "over_clause ::= OVER nm", - /* 346 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 347 */ "term ::= QNUMBER", - /* 348 */ "input ::= cmdlist", - /* 349 */ "cmdlist ::= cmdlist ecmd", - /* 350 */ "cmdlist ::= ecmd", - /* 351 */ "ecmd ::= SEMI", - /* 352 */ "ecmd ::= cmdx SEMI", - /* 353 */ "ecmd ::= explain cmdx SEMI", - /* 354 */ "trans_opt ::=", - /* 355 */ "trans_opt ::= TRANSACTION", - /* 356 */ "trans_opt ::= TRANSACTION nm", - /* 357 */ "savepoint_opt ::= SAVEPOINT", - /* 358 */ "savepoint_opt ::=", - /* 359 */ "cmd ::= create_table create_table_args", - /* 360 */ "table_option_set ::= table_option", - /* 361 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 362 */ "columnlist ::= columnname carglist", - /* 363 */ "nm ::= ID|INDEXED|JOIN_KW", - /* 364 */ "nm ::= STRING", - /* 365 */ "typetoken ::= typename", - /* 366 */ "typename ::= ID|STRING", - /* 367 */ "signed ::= plus_num", - /* 368 */ "signed ::= minus_num", - /* 369 */ "carglist ::= carglist ccons", - /* 370 */ "carglist ::=", - /* 371 */ "ccons ::= NULL onconf", - /* 372 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 373 */ "ccons ::= AS generated", - /* 374 */ "conslist_opt ::= COMMA conslist", - /* 375 */ "conslist ::= conslist tconscomma tcons", - /* 376 */ "conslist ::= tcons", - /* 377 */ "tconscomma ::=", - /* 378 */ "defer_subclause_opt ::= defer_subclause", - /* 379 */ "resolvetype ::= raisetype", - /* 380 */ "selectnowith ::= oneselect", - /* 381 */ "oneselect ::= values", - /* 382 */ "sclp ::= selcollist COMMA", - /* 383 */ "as ::= ID|STRING", - /* 384 */ "indexed_opt ::= indexed_by", - /* 385 */ "returning ::=", - /* 386 */ "expr ::= term", - /* 387 */ "likeop ::= LIKE_KW|MATCH", - /* 388 */ "case_operand ::= expr", - /* 389 */ "exprlist ::= nexprlist", - /* 390 */ "nmnum ::= plus_num", - /* 391 */ "nmnum ::= nm", - /* 392 */ "nmnum ::= ON", - /* 393 */ "nmnum ::= DELETE", - /* 394 */ "nmnum ::= DEFAULT", - /* 395 */ "plus_num ::= INTEGER|FLOAT", - /* 396 */ "foreach_clause ::=", - /* 397 */ "foreach_clause ::= FOR EACH ROW", - /* 398 */ "tridxby ::=", - /* 399 */ "database_kw_opt ::= DATABASE", - /* 400 */ "database_kw_opt ::=", - /* 401 */ "kwcolumn_opt ::=", - /* 402 */ "kwcolumn_opt ::= COLUMNKW", - /* 403 */ "vtabarglist ::= vtabarg", - /* 404 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 405 */ "vtabarg ::= vtabarg vtabargtoken", - /* 406 */ "anylist ::=", - /* 407 */ "anylist ::= anylist LP anylist RP", - /* 408 */ "anylist ::= anylist ANY", - /* 409 */ "with ::=", - /* 410 */ "windowdefn_list ::= windowdefn", - /* 411 */ "window ::= frame_opt", + /* 296 */ "add_column_fullname ::= fullname", + /* 297 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", + /* 298 */ "cmd ::= create_vtab", + /* 299 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 300 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 301 */ "vtabarg ::=", + /* 302 */ "vtabargtoken ::= ANY", + /* 303 */ "vtabargtoken ::= lp anylist RP", + /* 304 */ "lp ::= LP", + /* 305 */ "with ::= WITH wqlist", + /* 306 */ "with ::= WITH RECURSIVE wqlist", + /* 307 */ "wqas ::= AS", + /* 308 */ "wqas ::= AS MATERIALIZED", + /* 309 */ "wqas ::= AS NOT MATERIALIZED", + /* 310 */ "wqitem ::= withnm eidlist_opt wqas LP select RP", + /* 311 */ "withnm ::= nm", + /* 312 */ "wqlist ::= wqitem", + /* 313 */ "wqlist ::= wqlist COMMA wqitem", + /* 314 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", + /* 315 */ "windowdefn ::= nm AS LP window RP", + /* 316 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 317 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 318 */ "window ::= ORDER BY sortlist frame_opt", + /* 319 */ "window ::= nm ORDER BY sortlist frame_opt", + /* 320 */ "window ::= nm frame_opt", + /* 321 */ "frame_opt ::=", + /* 322 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", + /* 323 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", + /* 324 */ "range_or_rows ::= RANGE|ROWS|GROUPS", + /* 325 */ "frame_bound_s ::= frame_bound", + /* 326 */ "frame_bound_s ::= UNBOUNDED PRECEDING", + /* 327 */ "frame_bound_e ::= frame_bound", + /* 328 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", + /* 329 */ "frame_bound ::= expr PRECEDING|FOLLOWING", + /* 330 */ "frame_bound ::= CURRENT ROW", + /* 331 */ "frame_exclude_opt ::=", + /* 332 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", + /* 333 */ "frame_exclude ::= NO OTHERS", + /* 334 */ "frame_exclude ::= CURRENT ROW", + /* 335 */ "frame_exclude ::= GROUP|TIES", + /* 336 */ "window_clause ::= WINDOW windowdefn_list", + /* 337 */ "filter_over ::= filter_clause over_clause", + /* 338 */ "filter_over ::= over_clause", + /* 339 */ "filter_over ::= filter_clause", + /* 340 */ "over_clause ::= OVER LP window RP", + /* 341 */ "over_clause ::= OVER nm", + /* 342 */ "filter_clause ::= FILTER LP WHERE expr RP", + /* 343 */ "term ::= QNUMBER", + /* 344 */ "input ::= cmdlist", + /* 345 */ "cmdlist ::= cmdlist ecmd", + /* 346 */ "cmdlist ::= ecmd", + /* 347 */ "ecmd ::= SEMI", + /* 348 */ "ecmd ::= cmdx SEMI", + /* 349 */ "ecmd ::= explain cmdx SEMI", + /* 350 */ "trans_opt ::=", + /* 351 */ "trans_opt ::= TRANSACTION", + /* 352 */ "trans_opt ::= TRANSACTION nm", + /* 353 */ "savepoint_opt ::= SAVEPOINT", + /* 354 */ "savepoint_opt ::=", + /* 355 */ "cmd ::= create_table create_table_args", + /* 356 */ "table_option_set ::= table_option", + /* 357 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 358 */ "columnlist ::= columnname carglist", + /* 359 */ "nm ::= ID|INDEXED|JOIN_KW", + /* 360 */ "nm ::= STRING", + /* 361 */ "typetoken ::= typename", + /* 362 */ "typename ::= ID|STRING", + /* 363 */ "signed ::= plus_num", + /* 364 */ "signed ::= minus_num", + /* 365 */ "carglist ::= carglist ccons", + /* 366 */ "carglist ::=", + /* 367 */ "ccons ::= NULL onconf", + /* 368 */ "ccons ::= GENERATED ALWAYS AS generated", + /* 369 */ "ccons ::= AS generated", + /* 370 */ "conslist_opt ::= COMMA conslist", + /* 371 */ "conslist ::= conslist tconscomma tcons", + /* 372 */ "conslist ::= tcons", + /* 373 */ "tconscomma ::=", + /* 374 */ "defer_subclause_opt ::= defer_subclause", + /* 375 */ "resolvetype ::= raisetype", + /* 376 */ "selectnowith ::= oneselect", + /* 377 */ "oneselect ::= values", + /* 378 */ "sclp ::= selcollist COMMA", + /* 379 */ "as ::= ID|STRING", + /* 380 */ "indexed_opt ::= indexed_by", + /* 381 */ "returning ::=", + /* 382 */ "expr ::= term", + /* 383 */ "likeop ::= LIKE_KW|MATCH", + /* 384 */ "case_operand ::= expr", + /* 385 */ "exprlist ::= nexprlist", + /* 386 */ "nmnum ::= plus_num", + /* 387 */ "nmnum ::= nm", + /* 388 */ "nmnum ::= ON", + /* 389 */ "nmnum ::= DELETE", + /* 390 */ "nmnum ::= DEFAULT", + /* 391 */ "plus_num ::= INTEGER|FLOAT", + /* 392 */ "foreach_clause ::=", + /* 393 */ "foreach_clause ::= FOR EACH ROW", + /* 394 */ "trnm ::= nm", + /* 395 */ "tridxby ::=", + /* 396 */ "database_kw_opt ::= DATABASE", + /* 397 */ "database_kw_opt ::=", + /* 398 */ "kwcolumn_opt ::=", + /* 399 */ "kwcolumn_opt ::= COLUMNKW", + /* 400 */ "vtabarglist ::= vtabarg", + /* 401 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 402 */ "vtabarg ::= vtabarg vtabargtoken", + /* 403 */ "anylist ::=", + /* 404 */ "anylist ::= anylist LP anylist RP", + /* 405 */ "anylist ::= anylist ANY", + /* 406 */ "with ::=", + /* 407 */ "windowdefn_list ::= windowdefn", + /* 408 */ "window ::= frame_opt", }; #endif /* NDEBUG */ @@ -181121,24 +179859,15 @@ static int yyGrowStack(yyParser *p){ int newSize; int idx; yyStackEntry *pNew; -#ifdef YYSIZELIMIT - int nLimit = YYSIZELIMIT(sqlite3ParserCTX(p)); -#endif newSize = oldSize*2 + 100; -#ifdef YYSIZELIMIT - if( newSize>nLimit ){ - newSize = nLimit; - if( newSize<=oldSize ) return 1; - } -#endif idx = (int)(p->yytos - p->yystack); if( p->yystack==p->yystk0 ){ - pNew = YYREALLOC(0, newSize*sizeof(pNew[0]), sqlite3ParserCTX(p)); + pNew = YYREALLOC(0, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0])); }else{ - pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]), sqlite3ParserCTX(p)); + pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; } p->yystack = pNew; @@ -181245,7 +179974,7 @@ static void yy_destructor( case 254: /* values */ case 256: /* mvalues */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy555)); +sqlite3SelectDelete(pParse->db, (yypminor->yy637)); } break; case 218: /* term */ @@ -181257,10 +179986,10 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy555)); case 283: /* case_else */ case 286: /* vinto */ case 293: /* when_clause */ - case 297: /* key_opt */ - case 314: /* filter_clause */ + case 298: /* key_opt */ + case 315: /* filter_clause */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy454)); +sqlite3ExprDelete(pParse->db, (yypminor->yy590)); } break; case 223: /* eidlist_opt */ @@ -181275,9 +180004,9 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy454)); case 271: /* setlist */ case 280: /* paren_exprlist */ case 282: /* case_exprlist */ - case 313: /* part_opt */ + case 314: /* part_opt */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy402)); } break; case 240: /* fullname */ @@ -181286,51 +180015,51 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy14)); case 260: /* stl_prefix */ case 265: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy203)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy563)); } break; case 243: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy59)); +sqlite3WithDelete(pParse->db, (yypminor->yy125)); } break; case 253: /* window_clause */ - case 309: /* windowdefn_list */ + case 310: /* windowdefn_list */ { -sqlite3WindowListDelete(pParse->db, (yypminor->yy211)); +sqlite3WindowListDelete(pParse->db, (yypminor->yy483)); } break; case 266: /* idlist */ case 273: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy132)); +sqlite3IdListDelete(pParse->db, (yypminor->yy204)); } break; case 276: /* filter_over */ - case 310: /* windowdefn */ - case 311: /* window */ - case 312: /* frame_opt */ - case 315: /* over_clause */ + case 311: /* windowdefn */ + case 312: /* window */ + case 313: /* frame_opt */ + case 316: /* over_clause */ { -sqlite3WindowDelete(pParse->db, (yypminor->yy211)); +sqlite3WindowDelete(pParse->db, (yypminor->yy483)); } break; case 289: /* trigger_cmd_list */ case 294: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy427)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy319)); } break; case 291: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy286).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy28).b); } break; - case 317: /* frame_bound */ - case 318: /* frame_bound_s */ - case 319: /* frame_bound_e */ + case 318: /* frame_bound */ + case 319: /* frame_bound_s */ + case 320: /* frame_bound_e */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy509).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy205).pExpr); } break; /********* End destructor definitions *****************************************/ @@ -181383,9 +180112,7 @@ SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){ } #if YYGROWABLESTACK - if( pParser->yystack!=pParser->yystk0 ){ - YYFREE(pParser->yystack, sqlite3ParserCTX(pParser)); - } + if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack); #endif } @@ -181568,7 +180295,7 @@ static void yyStackOverflow(yyParser *yypParser){ ** stack every overflows */ /******** Begin %stack_overflow code ******************************************/ - if( pParse->nErr==0 ) sqlite3ErrorMsg(pParse, "Recursion limit"); + sqlite3OomFault(pParse->db); /******** End %stack_overflow code ********************************************/ sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument var */ sqlite3ParserCTX_STORE @@ -181756,8 +180483,8 @@ static const YYCODETYPE yyRuleInfoLhs[] = { 240, /* (119) fullname ::= nm DOT nm */ 265, /* (120) xfullname ::= nm */ 265, /* (121) xfullname ::= nm DOT nm */ - 265, /* (122) xfullname ::= nm AS nm */ - 265, /* (123) xfullname ::= nm DOT nm AS nm */ + 265, /* (122) xfullname ::= nm DOT nm AS nm */ + 265, /* (123) xfullname ::= nm AS nm */ 261, /* (124) joinop ::= COMMA|JOIN */ 261, /* (125) joinop ::= JOIN_KW JOIN */ 261, /* (126) joinop ::= JOIN_KW nm JOIN */ @@ -181906,146 +180633,143 @@ static const YYCODETYPE yyRuleInfoLhs[] = { 293, /* (269) when_clause ::= WHEN expr */ 289, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ 289, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - 295, /* (272) tridxby ::= INDEXED BY nm */ - 295, /* (273) tridxby ::= NOT INDEXED */ - 294, /* (274) trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */ - 294, /* (275) trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */ - 294, /* (276) trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */ - 294, /* (277) trigger_cmd ::= scanpt select scanpt */ - 219, /* (278) expr ::= RAISE LP IGNORE RP */ - 219, /* (279) expr ::= RAISE LP raisetype COMMA expr RP */ - 238, /* (280) raisetype ::= ROLLBACK */ - 238, /* (281) raisetype ::= ABORT */ - 238, /* (282) raisetype ::= FAIL */ - 192, /* (283) cmd ::= DROP TRIGGER ifexists fullname */ - 192, /* (284) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 192, /* (285) cmd ::= DETACH database_kw_opt expr */ - 297, /* (286) key_opt ::= */ - 297, /* (287) key_opt ::= KEY expr */ - 192, /* (288) cmd ::= REINDEX */ - 192, /* (289) cmd ::= REINDEX nm dbnm */ - 192, /* (290) cmd ::= ANALYZE */ - 192, /* (291) cmd ::= ANALYZE nm dbnm */ - 192, /* (292) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 192, /* (293) cmd ::= alter_add carglist */ - 298, /* (294) alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */ + 295, /* (272) trnm ::= nm DOT nm */ + 296, /* (273) tridxby ::= INDEXED BY nm */ + 296, /* (274) tridxby ::= NOT INDEXED */ + 294, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + 294, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + 294, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + 294, /* (278) trigger_cmd ::= scanpt select scanpt */ + 219, /* (279) expr ::= RAISE LP IGNORE RP */ + 219, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ + 238, /* (281) raisetype ::= ROLLBACK */ + 238, /* (282) raisetype ::= ABORT */ + 238, /* (283) raisetype ::= FAIL */ + 192, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ + 192, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + 192, /* (286) cmd ::= DETACH database_kw_opt expr */ + 298, /* (287) key_opt ::= */ + 298, /* (288) key_opt ::= KEY expr */ + 192, /* (289) cmd ::= REINDEX */ + 192, /* (290) cmd ::= REINDEX nm dbnm */ + 192, /* (291) cmd ::= ANALYZE */ + 192, /* (292) cmd ::= ANALYZE nm dbnm */ + 192, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ + 192, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ 192, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 192, /* (296) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 192, /* (297) cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */ - 192, /* (298) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */ - 192, /* (299) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */ - 192, /* (300) cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */ - 192, /* (301) cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */ - 192, /* (302) cmd ::= create_vtab */ - 192, /* (303) cmd ::= create_vtab LP vtabarglist RP */ - 300, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 302, /* (305) vtabarg ::= */ - 303, /* (306) vtabargtoken ::= ANY */ - 303, /* (307) vtabargtoken ::= lp anylist RP */ - 304, /* (308) lp ::= LP */ - 269, /* (309) with ::= WITH wqlist */ - 269, /* (310) with ::= WITH RECURSIVE wqlist */ - 307, /* (311) wqas ::= AS */ - 307, /* (312) wqas ::= AS MATERIALIZED */ - 307, /* (313) wqas ::= AS NOT MATERIALIZED */ - 306, /* (314) wqitem ::= withnm eidlist_opt wqas LP select RP */ - 308, /* (315) withnm ::= nm */ - 243, /* (316) wqlist ::= wqitem */ - 243, /* (317) wqlist ::= wqlist COMMA wqitem */ - 309, /* (318) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 310, /* (319) windowdefn ::= nm AS LP window RP */ - 311, /* (320) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 311, /* (321) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 311, /* (322) window ::= ORDER BY sortlist frame_opt */ - 311, /* (323) window ::= nm ORDER BY sortlist frame_opt */ - 311, /* (324) window ::= nm frame_opt */ - 312, /* (325) frame_opt ::= */ - 312, /* (326) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 312, /* (327) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 316, /* (328) range_or_rows ::= RANGE|ROWS|GROUPS */ - 318, /* (329) frame_bound_s ::= frame_bound */ - 318, /* (330) frame_bound_s ::= UNBOUNDED PRECEDING */ - 319, /* (331) frame_bound_e ::= frame_bound */ - 319, /* (332) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 317, /* (333) frame_bound ::= expr PRECEDING|FOLLOWING */ - 317, /* (334) frame_bound ::= CURRENT ROW */ - 320, /* (335) frame_exclude_opt ::= */ - 320, /* (336) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 321, /* (337) frame_exclude ::= NO OTHERS */ - 321, /* (338) frame_exclude ::= CURRENT ROW */ - 321, /* (339) frame_exclude ::= GROUP|TIES */ - 253, /* (340) window_clause ::= WINDOW windowdefn_list */ - 276, /* (341) filter_over ::= filter_clause over_clause */ - 276, /* (342) filter_over ::= over_clause */ - 276, /* (343) filter_over ::= filter_clause */ - 315, /* (344) over_clause ::= OVER LP window RP */ - 315, /* (345) over_clause ::= OVER nm */ - 314, /* (346) filter_clause ::= FILTER LP WHERE expr RP */ - 218, /* (347) term ::= QNUMBER */ - 187, /* (348) input ::= cmdlist */ - 188, /* (349) cmdlist ::= cmdlist ecmd */ - 188, /* (350) cmdlist ::= ecmd */ - 189, /* (351) ecmd ::= SEMI */ - 189, /* (352) ecmd ::= cmdx SEMI */ - 189, /* (353) ecmd ::= explain cmdx SEMI */ - 194, /* (354) trans_opt ::= */ - 194, /* (355) trans_opt ::= TRANSACTION */ - 194, /* (356) trans_opt ::= TRANSACTION nm */ - 196, /* (357) savepoint_opt ::= SAVEPOINT */ - 196, /* (358) savepoint_opt ::= */ - 192, /* (359) cmd ::= create_table create_table_args */ - 205, /* (360) table_option_set ::= table_option */ - 203, /* (361) columnlist ::= columnlist COMMA columnname carglist */ - 203, /* (362) columnlist ::= columnname carglist */ - 195, /* (363) nm ::= ID|INDEXED|JOIN_KW */ - 195, /* (364) nm ::= STRING */ - 210, /* (365) typetoken ::= typename */ - 211, /* (366) typename ::= ID|STRING */ - 212, /* (367) signed ::= plus_num */ - 212, /* (368) signed ::= minus_num */ - 209, /* (369) carglist ::= carglist ccons */ - 209, /* (370) carglist ::= */ - 217, /* (371) ccons ::= NULL onconf */ - 217, /* (372) ccons ::= GENERATED ALWAYS AS generated */ - 217, /* (373) ccons ::= AS generated */ - 204, /* (374) conslist_opt ::= COMMA conslist */ - 230, /* (375) conslist ::= conslist tconscomma tcons */ - 230, /* (376) conslist ::= tcons */ - 231, /* (377) tconscomma ::= */ - 235, /* (378) defer_subclause_opt ::= defer_subclause */ - 237, /* (379) resolvetype ::= raisetype */ - 241, /* (380) selectnowith ::= oneselect */ - 242, /* (381) oneselect ::= values */ - 257, /* (382) sclp ::= selcollist COMMA */ - 258, /* (383) as ::= ID|STRING */ - 267, /* (384) indexed_opt ::= indexed_by */ - 275, /* (385) returning ::= */ - 219, /* (386) expr ::= term */ - 277, /* (387) likeop ::= LIKE_KW|MATCH */ - 281, /* (388) case_operand ::= expr */ - 264, /* (389) exprlist ::= nexprlist */ - 287, /* (390) nmnum ::= plus_num */ - 287, /* (391) nmnum ::= nm */ - 287, /* (392) nmnum ::= ON */ - 287, /* (393) nmnum ::= DELETE */ - 287, /* (394) nmnum ::= DEFAULT */ - 213, /* (395) plus_num ::= INTEGER|FLOAT */ - 292, /* (396) foreach_clause ::= */ - 292, /* (397) foreach_clause ::= FOR EACH ROW */ - 295, /* (398) tridxby ::= */ - 296, /* (399) database_kw_opt ::= DATABASE */ - 296, /* (400) database_kw_opt ::= */ - 299, /* (401) kwcolumn_opt ::= */ - 299, /* (402) kwcolumn_opt ::= COLUMNKW */ - 301, /* (403) vtabarglist ::= vtabarg */ - 301, /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ - 302, /* (405) vtabarg ::= vtabarg vtabargtoken */ - 305, /* (406) anylist ::= */ - 305, /* (407) anylist ::= anylist LP anylist RP */ - 305, /* (408) anylist ::= anylist ANY */ - 269, /* (409) with ::= */ - 309, /* (410) windowdefn_list ::= windowdefn */ - 311, /* (411) window ::= frame_opt */ + 299, /* (296) add_column_fullname ::= fullname */ + 192, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + 192, /* (298) cmd ::= create_vtab */ + 192, /* (299) cmd ::= create_vtab LP vtabarglist RP */ + 301, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 303, /* (301) vtabarg ::= */ + 304, /* (302) vtabargtoken ::= ANY */ + 304, /* (303) vtabargtoken ::= lp anylist RP */ + 305, /* (304) lp ::= LP */ + 269, /* (305) with ::= WITH wqlist */ + 269, /* (306) with ::= WITH RECURSIVE wqlist */ + 308, /* (307) wqas ::= AS */ + 308, /* (308) wqas ::= AS MATERIALIZED */ + 308, /* (309) wqas ::= AS NOT MATERIALIZED */ + 307, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ + 309, /* (311) withnm ::= nm */ + 243, /* (312) wqlist ::= wqitem */ + 243, /* (313) wqlist ::= wqlist COMMA wqitem */ + 310, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 311, /* (315) windowdefn ::= nm AS LP window RP */ + 312, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 312, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 312, /* (318) window ::= ORDER BY sortlist frame_opt */ + 312, /* (319) window ::= nm ORDER BY sortlist frame_opt */ + 312, /* (320) window ::= nm frame_opt */ + 313, /* (321) frame_opt ::= */ + 313, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 313, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 317, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ + 319, /* (325) frame_bound_s ::= frame_bound */ + 319, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ + 320, /* (327) frame_bound_e ::= frame_bound */ + 320, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 318, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ + 318, /* (330) frame_bound ::= CURRENT ROW */ + 321, /* (331) frame_exclude_opt ::= */ + 321, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 322, /* (333) frame_exclude ::= NO OTHERS */ + 322, /* (334) frame_exclude ::= CURRENT ROW */ + 322, /* (335) frame_exclude ::= GROUP|TIES */ + 253, /* (336) window_clause ::= WINDOW windowdefn_list */ + 276, /* (337) filter_over ::= filter_clause over_clause */ + 276, /* (338) filter_over ::= over_clause */ + 276, /* (339) filter_over ::= filter_clause */ + 316, /* (340) over_clause ::= OVER LP window RP */ + 316, /* (341) over_clause ::= OVER nm */ + 315, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ + 218, /* (343) term ::= QNUMBER */ + 187, /* (344) input ::= cmdlist */ + 188, /* (345) cmdlist ::= cmdlist ecmd */ + 188, /* (346) cmdlist ::= ecmd */ + 189, /* (347) ecmd ::= SEMI */ + 189, /* (348) ecmd ::= cmdx SEMI */ + 189, /* (349) ecmd ::= explain cmdx SEMI */ + 194, /* (350) trans_opt ::= */ + 194, /* (351) trans_opt ::= TRANSACTION */ + 194, /* (352) trans_opt ::= TRANSACTION nm */ + 196, /* (353) savepoint_opt ::= SAVEPOINT */ + 196, /* (354) savepoint_opt ::= */ + 192, /* (355) cmd ::= create_table create_table_args */ + 205, /* (356) table_option_set ::= table_option */ + 203, /* (357) columnlist ::= columnlist COMMA columnname carglist */ + 203, /* (358) columnlist ::= columnname carglist */ + 195, /* (359) nm ::= ID|INDEXED|JOIN_KW */ + 195, /* (360) nm ::= STRING */ + 210, /* (361) typetoken ::= typename */ + 211, /* (362) typename ::= ID|STRING */ + 212, /* (363) signed ::= plus_num */ + 212, /* (364) signed ::= minus_num */ + 209, /* (365) carglist ::= carglist ccons */ + 209, /* (366) carglist ::= */ + 217, /* (367) ccons ::= NULL onconf */ + 217, /* (368) ccons ::= GENERATED ALWAYS AS generated */ + 217, /* (369) ccons ::= AS generated */ + 204, /* (370) conslist_opt ::= COMMA conslist */ + 230, /* (371) conslist ::= conslist tconscomma tcons */ + 230, /* (372) conslist ::= tcons */ + 231, /* (373) tconscomma ::= */ + 235, /* (374) defer_subclause_opt ::= defer_subclause */ + 237, /* (375) resolvetype ::= raisetype */ + 241, /* (376) selectnowith ::= oneselect */ + 242, /* (377) oneselect ::= values */ + 257, /* (378) sclp ::= selcollist COMMA */ + 258, /* (379) as ::= ID|STRING */ + 267, /* (380) indexed_opt ::= indexed_by */ + 275, /* (381) returning ::= */ + 219, /* (382) expr ::= term */ + 277, /* (383) likeop ::= LIKE_KW|MATCH */ + 281, /* (384) case_operand ::= expr */ + 264, /* (385) exprlist ::= nexprlist */ + 287, /* (386) nmnum ::= plus_num */ + 287, /* (387) nmnum ::= nm */ + 287, /* (388) nmnum ::= ON */ + 287, /* (389) nmnum ::= DELETE */ + 287, /* (390) nmnum ::= DEFAULT */ + 213, /* (391) plus_num ::= INTEGER|FLOAT */ + 292, /* (392) foreach_clause ::= */ + 292, /* (393) foreach_clause ::= FOR EACH ROW */ + 295, /* (394) trnm ::= nm */ + 296, /* (395) tridxby ::= */ + 297, /* (396) database_kw_opt ::= DATABASE */ + 297, /* (397) database_kw_opt ::= */ + 300, /* (398) kwcolumn_opt ::= */ + 300, /* (399) kwcolumn_opt ::= COLUMNKW */ + 302, /* (400) vtabarglist ::= vtabarg */ + 302, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ + 303, /* (402) vtabarg ::= vtabarg vtabargtoken */ + 306, /* (403) anylist ::= */ + 306, /* (404) anylist ::= anylist LP anylist RP */ + 306, /* (405) anylist ::= anylist ANY */ + 269, /* (406) with ::= */ + 310, /* (407) windowdefn_list ::= windowdefn */ + 312, /* (408) window ::= frame_opt */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -182173,8 +180897,8 @@ static const signed char yyRuleInfoNRhs[] = { -3, /* (119) fullname ::= nm DOT nm */ -1, /* (120) xfullname ::= nm */ -3, /* (121) xfullname ::= nm DOT nm */ - -3, /* (122) xfullname ::= nm AS nm */ - -5, /* (123) xfullname ::= nm DOT nm AS nm */ + -5, /* (122) xfullname ::= nm DOT nm AS nm */ + -3, /* (123) xfullname ::= nm AS nm */ -1, /* (124) joinop ::= COMMA|JOIN */ -2, /* (125) joinop ::= JOIN_KW JOIN */ -3, /* (126) joinop ::= JOIN_KW nm JOIN */ @@ -182323,146 +181047,143 @@ static const signed char yyRuleInfoNRhs[] = { -2, /* (269) when_clause ::= WHEN expr */ -3, /* (270) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ -2, /* (271) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (272) tridxby ::= INDEXED BY nm */ - -2, /* (273) tridxby ::= NOT INDEXED */ - -9, /* (274) trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */ - -8, /* (275) trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */ - -6, /* (276) trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */ - -3, /* (277) trigger_cmd ::= scanpt select scanpt */ - -4, /* (278) expr ::= RAISE LP IGNORE RP */ - -6, /* (279) expr ::= RAISE LP raisetype COMMA expr RP */ - -1, /* (280) raisetype ::= ROLLBACK */ - -1, /* (281) raisetype ::= ABORT */ - -1, /* (282) raisetype ::= FAIL */ - -4, /* (283) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (284) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (285) cmd ::= DETACH database_kw_opt expr */ - 0, /* (286) key_opt ::= */ - -2, /* (287) key_opt ::= KEY expr */ - -1, /* (288) cmd ::= REINDEX */ - -3, /* (289) cmd ::= REINDEX nm dbnm */ - -1, /* (290) cmd ::= ANALYZE */ - -3, /* (291) cmd ::= ANALYZE nm dbnm */ - -6, /* (292) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -2, /* (293) cmd ::= alter_add carglist */ - -7, /* (294) alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */ + -3, /* (272) trnm ::= nm DOT nm */ + -3, /* (273) tridxby ::= INDEXED BY nm */ + -2, /* (274) tridxby ::= NOT INDEXED */ + -9, /* (275) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + -8, /* (276) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + -6, /* (277) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + -3, /* (278) trigger_cmd ::= scanpt select scanpt */ + -4, /* (279) expr ::= RAISE LP IGNORE RP */ + -6, /* (280) expr ::= RAISE LP raisetype COMMA expr RP */ + -1, /* (281) raisetype ::= ROLLBACK */ + -1, /* (282) raisetype ::= ABORT */ + -1, /* (283) raisetype ::= FAIL */ + -4, /* (284) cmd ::= DROP TRIGGER ifexists fullname */ + -6, /* (285) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + -3, /* (286) cmd ::= DETACH database_kw_opt expr */ + 0, /* (287) key_opt ::= */ + -2, /* (288) key_opt ::= KEY expr */ + -1, /* (289) cmd ::= REINDEX */ + -3, /* (290) cmd ::= REINDEX nm dbnm */ + -1, /* (291) cmd ::= ANALYZE */ + -3, /* (292) cmd ::= ANALYZE nm dbnm */ + -6, /* (293) cmd ::= ALTER TABLE fullname RENAME TO nm */ + -7, /* (294) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ -6, /* (295) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -8, /* (296) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -6, /* (297) cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */ - -9, /* (298) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */ - -10, /* (299) cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */ - -11, /* (300) cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */ - -9, /* (301) cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */ - -1, /* (302) cmd ::= create_vtab */ - -4, /* (303) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (304) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (305) vtabarg ::= */ - -1, /* (306) vtabargtoken ::= ANY */ - -3, /* (307) vtabargtoken ::= lp anylist RP */ - -1, /* (308) lp ::= LP */ - -2, /* (309) with ::= WITH wqlist */ - -3, /* (310) with ::= WITH RECURSIVE wqlist */ - -1, /* (311) wqas ::= AS */ - -2, /* (312) wqas ::= AS MATERIALIZED */ - -3, /* (313) wqas ::= AS NOT MATERIALIZED */ - -6, /* (314) wqitem ::= withnm eidlist_opt wqas LP select RP */ - -1, /* (315) withnm ::= nm */ - -1, /* (316) wqlist ::= wqitem */ - -3, /* (317) wqlist ::= wqlist COMMA wqitem */ - -3, /* (318) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (319) windowdefn ::= nm AS LP window RP */ - -5, /* (320) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (321) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (322) window ::= ORDER BY sortlist frame_opt */ - -5, /* (323) window ::= nm ORDER BY sortlist frame_opt */ - -2, /* (324) window ::= nm frame_opt */ - 0, /* (325) frame_opt ::= */ - -3, /* (326) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (327) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (328) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (329) frame_bound_s ::= frame_bound */ - -2, /* (330) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (331) frame_bound_e ::= frame_bound */ - -2, /* (332) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (333) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (334) frame_bound ::= CURRENT ROW */ - 0, /* (335) frame_exclude_opt ::= */ - -2, /* (336) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (337) frame_exclude ::= NO OTHERS */ - -2, /* (338) frame_exclude ::= CURRENT ROW */ - -1, /* (339) frame_exclude ::= GROUP|TIES */ - -2, /* (340) window_clause ::= WINDOW windowdefn_list */ - -2, /* (341) filter_over ::= filter_clause over_clause */ - -1, /* (342) filter_over ::= over_clause */ - -1, /* (343) filter_over ::= filter_clause */ - -4, /* (344) over_clause ::= OVER LP window RP */ - -2, /* (345) over_clause ::= OVER nm */ - -5, /* (346) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (347) term ::= QNUMBER */ - -1, /* (348) input ::= cmdlist */ - -2, /* (349) cmdlist ::= cmdlist ecmd */ - -1, /* (350) cmdlist ::= ecmd */ - -1, /* (351) ecmd ::= SEMI */ - -2, /* (352) ecmd ::= cmdx SEMI */ - -3, /* (353) ecmd ::= explain cmdx SEMI */ - 0, /* (354) trans_opt ::= */ - -1, /* (355) trans_opt ::= TRANSACTION */ - -2, /* (356) trans_opt ::= TRANSACTION nm */ - -1, /* (357) savepoint_opt ::= SAVEPOINT */ - 0, /* (358) savepoint_opt ::= */ - -2, /* (359) cmd ::= create_table create_table_args */ - -1, /* (360) table_option_set ::= table_option */ - -4, /* (361) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (362) columnlist ::= columnname carglist */ - -1, /* (363) nm ::= ID|INDEXED|JOIN_KW */ - -1, /* (364) nm ::= STRING */ - -1, /* (365) typetoken ::= typename */ - -1, /* (366) typename ::= ID|STRING */ - -1, /* (367) signed ::= plus_num */ - -1, /* (368) signed ::= minus_num */ - -2, /* (369) carglist ::= carglist ccons */ - 0, /* (370) carglist ::= */ - -2, /* (371) ccons ::= NULL onconf */ - -4, /* (372) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (373) ccons ::= AS generated */ - -2, /* (374) conslist_opt ::= COMMA conslist */ - -3, /* (375) conslist ::= conslist tconscomma tcons */ - -1, /* (376) conslist ::= tcons */ - 0, /* (377) tconscomma ::= */ - -1, /* (378) defer_subclause_opt ::= defer_subclause */ - -1, /* (379) resolvetype ::= raisetype */ - -1, /* (380) selectnowith ::= oneselect */ - -1, /* (381) oneselect ::= values */ - -2, /* (382) sclp ::= selcollist COMMA */ - -1, /* (383) as ::= ID|STRING */ - -1, /* (384) indexed_opt ::= indexed_by */ - 0, /* (385) returning ::= */ - -1, /* (386) expr ::= term */ - -1, /* (387) likeop ::= LIKE_KW|MATCH */ - -1, /* (388) case_operand ::= expr */ - -1, /* (389) exprlist ::= nexprlist */ - -1, /* (390) nmnum ::= plus_num */ - -1, /* (391) nmnum ::= nm */ - -1, /* (392) nmnum ::= ON */ - -1, /* (393) nmnum ::= DELETE */ - -1, /* (394) nmnum ::= DEFAULT */ - -1, /* (395) plus_num ::= INTEGER|FLOAT */ - 0, /* (396) foreach_clause ::= */ - -3, /* (397) foreach_clause ::= FOR EACH ROW */ - 0, /* (398) tridxby ::= */ - -1, /* (399) database_kw_opt ::= DATABASE */ - 0, /* (400) database_kw_opt ::= */ - 0, /* (401) kwcolumn_opt ::= */ - -1, /* (402) kwcolumn_opt ::= COLUMNKW */ - -1, /* (403) vtabarglist ::= vtabarg */ - -3, /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (405) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (406) anylist ::= */ - -4, /* (407) anylist ::= anylist LP anylist RP */ - -2, /* (408) anylist ::= anylist ANY */ - 0, /* (409) with ::= */ - -1, /* (410) windowdefn_list ::= windowdefn */ - -1, /* (411) window ::= frame_opt */ + -1, /* (296) add_column_fullname ::= fullname */ + -8, /* (297) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + -1, /* (298) cmd ::= create_vtab */ + -4, /* (299) cmd ::= create_vtab LP vtabarglist RP */ + -8, /* (300) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 0, /* (301) vtabarg ::= */ + -1, /* (302) vtabargtoken ::= ANY */ + -3, /* (303) vtabargtoken ::= lp anylist RP */ + -1, /* (304) lp ::= LP */ + -2, /* (305) with ::= WITH wqlist */ + -3, /* (306) with ::= WITH RECURSIVE wqlist */ + -1, /* (307) wqas ::= AS */ + -2, /* (308) wqas ::= AS MATERIALIZED */ + -3, /* (309) wqas ::= AS NOT MATERIALIZED */ + -6, /* (310) wqitem ::= withnm eidlist_opt wqas LP select RP */ + -1, /* (311) withnm ::= nm */ + -1, /* (312) wqlist ::= wqitem */ + -3, /* (313) wqlist ::= wqlist COMMA wqitem */ + -3, /* (314) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + -5, /* (315) windowdefn ::= nm AS LP window RP */ + -5, /* (316) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (317) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (318) window ::= ORDER BY sortlist frame_opt */ + -5, /* (319) window ::= nm ORDER BY sortlist frame_opt */ + -2, /* (320) window ::= nm frame_opt */ + 0, /* (321) frame_opt ::= */ + -3, /* (322) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + -6, /* (323) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + -1, /* (324) range_or_rows ::= RANGE|ROWS|GROUPS */ + -1, /* (325) frame_bound_s ::= frame_bound */ + -2, /* (326) frame_bound_s ::= UNBOUNDED PRECEDING */ + -1, /* (327) frame_bound_e ::= frame_bound */ + -2, /* (328) frame_bound_e ::= UNBOUNDED FOLLOWING */ + -2, /* (329) frame_bound ::= expr PRECEDING|FOLLOWING */ + -2, /* (330) frame_bound ::= CURRENT ROW */ + 0, /* (331) frame_exclude_opt ::= */ + -2, /* (332) frame_exclude_opt ::= EXCLUDE frame_exclude */ + -2, /* (333) frame_exclude ::= NO OTHERS */ + -2, /* (334) frame_exclude ::= CURRENT ROW */ + -1, /* (335) frame_exclude ::= GROUP|TIES */ + -2, /* (336) window_clause ::= WINDOW windowdefn_list */ + -2, /* (337) filter_over ::= filter_clause over_clause */ + -1, /* (338) filter_over ::= over_clause */ + -1, /* (339) filter_over ::= filter_clause */ + -4, /* (340) over_clause ::= OVER LP window RP */ + -2, /* (341) over_clause ::= OVER nm */ + -5, /* (342) filter_clause ::= FILTER LP WHERE expr RP */ + -1, /* (343) term ::= QNUMBER */ + -1, /* (344) input ::= cmdlist */ + -2, /* (345) cmdlist ::= cmdlist ecmd */ + -1, /* (346) cmdlist ::= ecmd */ + -1, /* (347) ecmd ::= SEMI */ + -2, /* (348) ecmd ::= cmdx SEMI */ + -3, /* (349) ecmd ::= explain cmdx SEMI */ + 0, /* (350) trans_opt ::= */ + -1, /* (351) trans_opt ::= TRANSACTION */ + -2, /* (352) trans_opt ::= TRANSACTION nm */ + -1, /* (353) savepoint_opt ::= SAVEPOINT */ + 0, /* (354) savepoint_opt ::= */ + -2, /* (355) cmd ::= create_table create_table_args */ + -1, /* (356) table_option_set ::= table_option */ + -4, /* (357) columnlist ::= columnlist COMMA columnname carglist */ + -2, /* (358) columnlist ::= columnname carglist */ + -1, /* (359) nm ::= ID|INDEXED|JOIN_KW */ + -1, /* (360) nm ::= STRING */ + -1, /* (361) typetoken ::= typename */ + -1, /* (362) typename ::= ID|STRING */ + -1, /* (363) signed ::= plus_num */ + -1, /* (364) signed ::= minus_num */ + -2, /* (365) carglist ::= carglist ccons */ + 0, /* (366) carglist ::= */ + -2, /* (367) ccons ::= NULL onconf */ + -4, /* (368) ccons ::= GENERATED ALWAYS AS generated */ + -2, /* (369) ccons ::= AS generated */ + -2, /* (370) conslist_opt ::= COMMA conslist */ + -3, /* (371) conslist ::= conslist tconscomma tcons */ + -1, /* (372) conslist ::= tcons */ + 0, /* (373) tconscomma ::= */ + -1, /* (374) defer_subclause_opt ::= defer_subclause */ + -1, /* (375) resolvetype ::= raisetype */ + -1, /* (376) selectnowith ::= oneselect */ + -1, /* (377) oneselect ::= values */ + -2, /* (378) sclp ::= selcollist COMMA */ + -1, /* (379) as ::= ID|STRING */ + -1, /* (380) indexed_opt ::= indexed_by */ + 0, /* (381) returning ::= */ + -1, /* (382) expr ::= term */ + -1, /* (383) likeop ::= LIKE_KW|MATCH */ + -1, /* (384) case_operand ::= expr */ + -1, /* (385) exprlist ::= nexprlist */ + -1, /* (386) nmnum ::= plus_num */ + -1, /* (387) nmnum ::= nm */ + -1, /* (388) nmnum ::= ON */ + -1, /* (389) nmnum ::= DELETE */ + -1, /* (390) nmnum ::= DEFAULT */ + -1, /* (391) plus_num ::= INTEGER|FLOAT */ + 0, /* (392) foreach_clause ::= */ + -3, /* (393) foreach_clause ::= FOR EACH ROW */ + -1, /* (394) trnm ::= nm */ + 0, /* (395) tridxby ::= */ + -1, /* (396) database_kw_opt ::= DATABASE */ + 0, /* (397) database_kw_opt ::= */ + 0, /* (398) kwcolumn_opt ::= */ + -1, /* (399) kwcolumn_opt ::= COLUMNKW */ + -1, /* (400) vtabarglist ::= vtabarg */ + -3, /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ + -2, /* (402) vtabarg ::= vtabarg vtabargtoken */ + 0, /* (403) anylist ::= */ + -4, /* (404) anylist ::= anylist LP anylist RP */ + -2, /* (405) anylist ::= anylist ANY */ + 0, /* (406) with ::= */ + -1, /* (407) windowdefn_list ::= windowdefn */ + -1, /* (408) window ::= frame_opt */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -182514,16 +181235,16 @@ static YYACTIONTYPE yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy144);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy144 = TK_DEFERRED;} +{yymsp[1].minor.yy502 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 328: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==328); -{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/} + case 324: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==324); +{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); @@ -182546,7 +181267,7 @@ static YYACTIONTYPE yy_reduce( break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy144,0,0,yymsp[-2].minor.yy144); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502); } break; case 14: /* createkw ::= CREATE */ @@ -182562,38 +181283,38 @@ static YYACTIONTYPE yy_reduce( case 81: /* ifexists ::= */ yytestcase(yyruleno==81); case 100: /* distinct ::= */ yytestcase(yyruleno==100); case 246: /* collate ::= */ yytestcase(yyruleno==246); -{yymsp[1].minor.yy144 = 0;} +{yymsp[1].minor.yy502 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy144 = 1;} +{yymsp[-2].minor.yy502 = 1;} break; case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy144 = pParse->db->init.busy==0;} +{yymsp[0].minor.yy502 = pParse->db->init.busy==0;} break; case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy391,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy9,0); } break; case 20: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy555); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy637); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); } break; case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy391 = 0;} +{yymsp[1].minor.yy9 = 0;} break; case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy391 = yymsp[-2].minor.yy391|yymsp[0].minor.yy391;} - yymsp[-2].minor.yy391 = yylhsminor.yy391; +{yylhsminor.yy9 = yymsp[-2].minor.yy9|yymsp[0].minor.yy9;} + yymsp[-2].minor.yy9 = yylhsminor.yy9; break; case 23: /* table_option ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy391 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy9 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy391 = 0; + yymsp[-1].minor.yy9 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -182601,13 +181322,13 @@ static YYACTIONTYPE yy_reduce( case 24: /* table_option ::= nm */ { if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy391 = TF_Strict; + yylhsminor.yy9 = TF_Strict; }else{ - yylhsminor.yy391 = 0; + yylhsminor.yy9 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } - yymsp[0].minor.yy391 = yylhsminor.yy391; + yymsp[0].minor.yy9 = yylhsminor.yy9; break; case 25: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} @@ -182633,7 +181354,7 @@ static YYACTIONTYPE yy_reduce( case 30: /* scanpt ::= */ { assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy168 = yyLookaheadToken.z; + yymsp[1].minor.yy342 = yyLookaheadToken.z; } break; case 31: /* scantok ::= */ @@ -182647,17 +181368,17 @@ static YYACTIONTYPE yy_reduce( {ASSERT_IS_CREATE; pParse->u1.cr.constraintName = yymsp[0].minor.yy0;} break; case 33: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 34: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; case 35: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy454,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy590,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 36: /* ccons ::= DEFAULT MINUS scantok term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy454, 0); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy590, 0); sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); } break; @@ -182672,133 +181393,133 @@ static YYACTIONTYPE yy_reduce( } break; case 38: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy144);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);} break; case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy144,yymsp[0].minor.yy144,yymsp[-2].minor.yy144);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);} break; case 40: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy144,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 41: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy454,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy590,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} break; case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy14,yymsp[0].minor.yy144);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy502);} break; case 43: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy144);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);} break; case 44: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 45: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy454,0);} +{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy590,0);} break; case 46: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy454,&yymsp[0].minor.yy0);} +{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy590,&yymsp[0].minor.yy0);} break; case 48: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy144 = 1;} +{yymsp[0].minor.yy502 = 1;} break; case 49: /* refargs ::= */ -{ yymsp[1].minor.yy144 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 50: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy144 = (yymsp[-1].minor.yy144 & ~yymsp[0].minor.yy383.mask) | yymsp[0].minor.yy383.value; } +{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy481.mask) | yymsp[0].minor.yy481.value; } break; case 51: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy383.value = 0; yymsp[-1].minor.yy383.mask = 0x000000; } +{ yymsp[-1].minor.yy481.value = 0; yymsp[-1].minor.yy481.mask = 0x000000; } break; case 52: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy383.value = 0; yymsp[-2].minor.yy383.mask = 0x000000; } +{ yymsp[-2].minor.yy481.value = 0; yymsp[-2].minor.yy481.mask = 0x000000; } break; case 53: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144; yymsp[-2].minor.yy383.mask = 0x0000ff; } +{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy481.mask = 0x0000ff; } break; case 54: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy383.value = yymsp[0].minor.yy144<<8; yymsp[-2].minor.yy383.mask = 0x00ff00; } +{ yymsp[-2].minor.yy481.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy481.mask = 0x00ff00; } break; case 55: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy144 = OE_SetNull; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */} break; case 56: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy144 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 57: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy144 = OE_Cascade; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */} break; case 58: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy144 = OE_Restrict; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */} break; case 59: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy144 = OE_None; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */} break; case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy144 = 0;} +{yymsp[-2].minor.yy502 = 0;} break; case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76); case 173: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==173); -{yymsp[-1].minor.yy144 = yymsp[0].minor.yy144;} +{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;} break; case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80); case 219: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==219); case 222: /* in_op ::= NOT IN */ yytestcase(yyruleno==222); case 247: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==247); -{yymsp[-1].minor.yy144 = 1;} +{yymsp[-1].minor.yy502 = 1;} break; case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy144 = 0;} +{yymsp[-1].minor.yy502 = 0;} break; case 66: /* tconscomma ::= COMMA */ {ASSERT_IS_CREATE; pParse->u1.cr.constraintName.n = 0;} break; case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy14,yymsp[0].minor.yy144,yymsp[-2].minor.yy144,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);} break; case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy14,yymsp[0].minor.yy144,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy502,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 70: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy454,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy590,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} break; case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy14, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[-1].minor.yy144); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy144); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy502); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502); } break; case 73: /* onconf ::= */ case 75: /* orconf ::= */ yytestcase(yyruleno==75); -{yymsp[1].minor.yy144 = OE_Default;} +{yymsp[1].minor.yy502 = OE_Default;} break; case 74: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy144 = yymsp[0].minor.yy144;} +{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;} break; case 77: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy144 = OE_Ignore;} +{yymsp[0].minor.yy502 = OE_Ignore;} break; case 78: /* resolvetype ::= REPLACE */ case 174: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==174); -{yymsp[0].minor.yy144 = OE_Replace;} +{yymsp[0].minor.yy502 = OE_Replace;} break; case 79: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy203, 0, yymsp[-1].minor.yy144); + sqlite3DropTable(pParse, yymsp[0].minor.yy563, 0, yymsp[-1].minor.yy502); } break; case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy14, yymsp[0].minor.yy555, yymsp[-7].minor.yy144, yymsp[-5].minor.yy144); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy637, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502); } break; case 83: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy203, 1, yymsp[-1].minor.yy144); + sqlite3DropTable(pParse, yymsp[0].minor.yy563, 1, yymsp[-1].minor.yy502); } break; case 84: /* cmd ::= select */ @@ -182807,20 +181528,20 @@ static YYACTIONTYPE yy_reduce( if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0 || sqlite3ReadSchema(pParse)==SQLITE_OK ){ - sqlite3Select(pParse, yymsp[0].minor.yy555, &dest); + sqlite3Select(pParse, yymsp[0].minor.yy637, &dest); } - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy637); } break; case 85: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} +{yymsp[-2].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} break; case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);} +{yymsp[-3].minor.yy637 = attachWithToSelect(pParse,yymsp[0].minor.yy637,yymsp[-1].minor.yy125);} break; case 87: /* select ::= selectnowith */ { - Select *p = yymsp[0].minor.yy555; + Select *p = yymsp[0].minor.yy637; if( p ){ parserDoubleLinkSelect(pParse, p); } @@ -182828,8 +181549,8 @@ static YYACTIONTYPE yy_reduce( break; case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy555; - Select *pLhs = yymsp[-2].minor.yy555; + Select *pRhs = yymsp[0].minor.yy637; + Select *pLhs = yymsp[-2].minor.yy637; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -182839,60 +181560,60 @@ static YYACTIONTYPE yy_reduce( pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy144; + pRhs->op = (u8)yymsp[-1].minor.yy502; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue; pRhs->selFlags &= ~(u32)SF_MultiValue; - if( yymsp[-1].minor.yy144!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy555 = pRhs; + yymsp[-2].minor.yy637 = pRhs; } break; case 89: /* multiselect_op ::= UNION */ case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91); -{yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-OP*/} +{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/} break; case 90: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy144 = TK_ALL;} +{yymsp[-1].minor.yy502 = TK_ALL;} break; case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yymsp[-8].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy14,yymsp[-5].minor.yy203,yymsp[-4].minor.yy454,yymsp[-3].minor.yy14,yymsp[-2].minor.yy454,yymsp[-1].minor.yy14,yymsp[-7].minor.yy144,yymsp[0].minor.yy454); + yymsp[-8].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy563,yymsp[-4].minor.yy590,yymsp[-3].minor.yy402,yymsp[-2].minor.yy590,yymsp[-1].minor.yy402,yymsp[-7].minor.yy502,yymsp[0].minor.yy590); } break; case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ { - yymsp[-9].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy14,yymsp[-6].minor.yy203,yymsp[-5].minor.yy454,yymsp[-4].minor.yy14,yymsp[-3].minor.yy454,yymsp[-1].minor.yy14,yymsp[-8].minor.yy144,yymsp[0].minor.yy454); - if( yymsp[-9].minor.yy555 ){ - yymsp[-9].minor.yy555->pWinDefn = yymsp[-2].minor.yy211; + yymsp[-9].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy402,yymsp[-6].minor.yy563,yymsp[-5].minor.yy590,yymsp[-4].minor.yy402,yymsp[-3].minor.yy590,yymsp[-1].minor.yy402,yymsp[-8].minor.yy502,yymsp[0].minor.yy590); + if( yymsp[-9].minor.yy637 ){ + yymsp[-9].minor.yy637->pWinDefn = yymsp[-2].minor.yy483; }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy211); + sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy483); } } break; case 94: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy555 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0); + yymsp[-3].minor.yy637 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0); } break; case 95: /* oneselect ::= mvalues */ { - sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy555); + sqlite3MultiValuesEnd(pParse, yymsp[0].minor.yy637); } break; case 96: /* mvalues ::= values COMMA LP nexprlist RP */ case 97: /* mvalues ::= mvalues COMMA LP nexprlist RP */ yytestcase(yyruleno==97); { - yymsp[-4].minor.yy555 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy555, yymsp[-1].minor.yy14); + yymsp[-4].minor.yy637 = sqlite3MultiValues(pParse, yymsp[-4].minor.yy637, yymsp[-1].minor.yy402); } break; case 98: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy144 = SF_Distinct;} +{yymsp[0].minor.yy502 = SF_Distinct;} break; case 99: /* distinct ::= ALL */ -{yymsp[0].minor.yy144 = SF_All;} +{yymsp[0].minor.yy502 = SF_All;} break; case 101: /* sclp ::= */ case 134: /* orderby_opt ::= */ yytestcase(yyruleno==134); @@ -182900,20 +181621,20 @@ static YYACTIONTYPE yy_reduce( case 234: /* exprlist ::= */ yytestcase(yyruleno==234); case 237: /* paren_exprlist ::= */ yytestcase(yyruleno==237); case 242: /* eidlist_opt ::= */ yytestcase(yyruleno==242); -{yymsp[1].minor.yy14 = 0;} +{yymsp[1].minor.yy402 = 0;} break; case 102: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy14,yymsp[-3].minor.yy168,yymsp[-1].minor.yy168); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy342,yymsp[-1].minor.yy342); } break; case 103: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); sqlite3ExprSetErrorOffset(p, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); - yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy14, p); + yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p); } break; case 104: /* selcollist ::= sclp scanpt nm DOT STAR */ @@ -182923,7 +181644,7 @@ static YYACTIONTYPE yy_reduce( sqlite3ExprSetErrorOffset(pRight, (int)(yymsp[0].minor.yy0.z - pParse->zTail)); pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, pDot); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot); } break; case 105: /* as ::= AS nm */ @@ -182934,50 +181655,50 @@ static YYACTIONTYPE yy_reduce( break; case 107: /* from ::= */ case 110: /* stl_prefix ::= */ yytestcase(yyruleno==110); -{yymsp[1].minor.yy203 = 0;} +{yymsp[1].minor.yy563 = 0;} break; case 108: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy203 = yymsp[0].minor.yy203; - sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy203); + yymsp[-1].minor.yy563 = yymsp[0].minor.yy563; + sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy563); } break; case 109: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy203 && yymsp[-1].minor.yy203->nSrc>0) ) yymsp[-1].minor.yy203->a[yymsp[-1].minor.yy203->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy144; + if( ALWAYS(yymsp[-1].minor.yy563 && yymsp[-1].minor.yy563->nSrc>0) ) yymsp[-1].minor.yy563->a[yymsp[-1].minor.yy563->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502; } break; case 111: /* seltablist ::= stl_prefix nm dbnm as on_using */ { - yymsp[-4].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy203,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); + yymsp[-4].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy563,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); } break; case 112: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ { - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy269); - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-1].minor.yy0); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy421); + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-1].minor.yy0); } break; case 113: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ { - yymsp[-7].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy203,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); - sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy203, yymsp[-3].minor.yy14); + yymsp[-7].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy563,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); + sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy563, yymsp[-3].minor.yy402); } break; case 114: /* seltablist ::= stl_prefix LP select RP as on_using */ { - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy555,&yymsp[0].minor.yy269); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy637,&yymsp[0].minor.yy421); } break; case 115: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ { - if( yymsp[-5].minor.yy203==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy269.pOn==0 && yymsp[0].minor.yy269.pUsing==0 ){ - yymsp[-5].minor.yy203 = yymsp[-3].minor.yy203; - }else if( ALWAYS(yymsp[-3].minor.yy203!=0) && yymsp[-3].minor.yy203->nSrc==1 ){ - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy269); - if( yymsp[-5].minor.yy203 ){ - SrcItem *pNew = &yymsp[-5].minor.yy203->a[yymsp[-5].minor.yy203->nSrc-1]; - SrcItem *pOld = yymsp[-3].minor.yy203->a; + if( yymsp[-5].minor.yy563==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy421.pOn==0 && yymsp[0].minor.yy421.pUsing==0 ){ + yymsp[-5].minor.yy563 = yymsp[-3].minor.yy563; + }else if( ALWAYS(yymsp[-3].minor.yy563!=0) && yymsp[-3].minor.yy563->nSrc==1 ){ + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy421); + if( yymsp[-5].minor.yy563 ){ + SrcItem *pNew = &yymsp[-5].minor.yy563->a[yymsp[-5].minor.yy563->nSrc-1]; + SrcItem *pOld = yymsp[-3].minor.yy563->a; assert( pOld->fg.fixedSchema==0 ); pNew->zName = pOld->zName; assert( pOld->fg.fixedSchema==0 ); @@ -183002,12 +181723,12 @@ static YYACTIONTYPE yy_reduce( } pOld->zName = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy203); + sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy563); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy203); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy203,0,0,0,0,SF_NestedFrom,0); - yymsp[-5].minor.yy203 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy203,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy269); + sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy563); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy563,0,0,0,0,SF_NestedFrom,0); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy563,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy421); } } break; @@ -183016,67 +181737,57 @@ static YYACTIONTYPE yy_reduce( {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; case 118: /* fullname ::= nm */ - case 120: /* xfullname ::= nm */ yytestcase(yyruleno==120); { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); + if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy203 = yylhsminor.yy203; + yymsp[0].minor.yy563 = yylhsminor.yy563; break; case 119: /* fullname ::= nm DOT nm */ - case 121: /* xfullname ::= nm DOT nm */ yytestcase(yyruleno==121); { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy203 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + if( IN_RENAME_OBJECT && yylhsminor.yy563 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy563->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy203 = yylhsminor.yy203; + yymsp[-2].minor.yy563 = yylhsminor.yy563; break; - case 122: /* xfullname ::= nm AS nm */ + case 120: /* xfullname ::= nm */ +{yymsp[0].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} + break; + case 121: /* xfullname ::= nm DOT nm */ +{yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 122: /* xfullname ::= nm DOT nm AS nm */ { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); - if( yylhsminor.yy203 ){ - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[-2].minor.yy0); - }else{ - yylhsminor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); - } - } + yymsp[-4].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy563 ) yymsp[-4].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy203 = yylhsminor.yy203; break; - case 123: /* xfullname ::= nm DOT nm AS nm */ + case 123: /* xfullname ::= nm AS nm */ { - yylhsminor.yy203 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); - if( yylhsminor.yy203 ){ - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, yylhsminor.yy203->a[0].zName, &yymsp[-2].minor.yy0); - }else{ - yylhsminor.yy203->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); - } - } + yymsp[-2].minor.yy563 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy563 ) yymsp[-2].minor.yy563->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } - yymsp[-4].minor.yy203 = yylhsminor.yy203; break; case 124: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy144 = JT_INNER; } +{ yymsp[0].minor.yy502 = JT_INNER; } break; case 125: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} +{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; case 126: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} +{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; case 127: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy144 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} +{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; case 128: /* on_using ::= ON expr */ -{yymsp[-1].minor.yy269.pOn = yymsp[0].minor.yy454; yymsp[-1].minor.yy269.pUsing = 0;} +{yymsp[-1].minor.yy421.pOn = yymsp[0].minor.yy590; yymsp[-1].minor.yy421.pUsing = 0;} break; case 129: /* on_using ::= USING LP idlist RP */ -{yymsp[-3].minor.yy269.pOn = 0; yymsp[-3].minor.yy269.pUsing = yymsp[-1].minor.yy132;} +{yymsp[-3].minor.yy421.pOn = 0; yymsp[-3].minor.yy421.pUsing = yymsp[-1].minor.yy204;} break; case 130: /* on_using ::= */ -{yymsp[1].minor.yy269.pOn = 0; yymsp[1].minor.yy269.pUsing = 0;} +{yymsp[1].minor.yy421.pOn = 0; yymsp[1].minor.yy421.pUsing = 0;} break; case 132: /* indexed_by ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} @@ -183086,35 +181797,35 @@ static YYACTIONTYPE yy_reduce( break; case 135: /* orderby_opt ::= ORDER BY sortlist */ case 145: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==145); -{yymsp[-2].minor.yy14 = yymsp[0].minor.yy14;} +{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;} break; case 136: /* sortlist ::= sortlist COMMA expr sortorder nulls */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14,yymsp[-2].minor.yy454); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402,yymsp[-2].minor.yy590); + sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); } break; case 137: /* sortlist ::= expr sortorder nulls */ { - yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy454); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy14,yymsp[-1].minor.yy144,yymsp[0].minor.yy144); + yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy590); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy402,yymsp[-1].minor.yy502,yymsp[0].minor.yy502); } break; case 138: /* sortorder ::= ASC */ -{yymsp[0].minor.yy144 = SQLITE_SO_ASC;} +{yymsp[0].minor.yy502 = SQLITE_SO_ASC;} break; case 139: /* sortorder ::= DESC */ -{yymsp[0].minor.yy144 = SQLITE_SO_DESC;} +{yymsp[0].minor.yy502 = SQLITE_SO_DESC;} break; case 140: /* sortorder ::= */ case 143: /* nulls ::= */ yytestcase(yyruleno==143); -{yymsp[1].minor.yy144 = SQLITE_SO_UNDEFINED;} +{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;} break; case 141: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy144 = SQLITE_SO_ASC;} +{yymsp[-1].minor.yy502 = SQLITE_SO_ASC;} break; case 142: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy144 = SQLITE_SO_DESC;} +{yymsp[-1].minor.yy502 = SQLITE_SO_DESC;} break; case 146: /* having_opt ::= */ case 148: /* limit_opt ::= */ yytestcase(yyruleno==148); @@ -183123,42 +181834,42 @@ static YYACTIONTYPE yy_reduce( case 232: /* case_else ::= */ yytestcase(yyruleno==232); case 233: /* case_operand ::= */ yytestcase(yyruleno==233); case 252: /* vinto ::= */ yytestcase(yyruleno==252); -{yymsp[1].minor.yy454 = 0;} +{yymsp[1].minor.yy590 = 0;} break; case 147: /* having_opt ::= HAVING expr */ case 154: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==154); case 156: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==156); case 231: /* case_else ::= ELSE expr */ yytestcase(yyruleno==231); case 251: /* vinto ::= INTO expr */ yytestcase(yyruleno==251); -{yymsp[-1].minor.yy454 = yymsp[0].minor.yy454;} +{yymsp[-1].minor.yy590 = yymsp[0].minor.yy590;} break; case 149: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,0);} +{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,0);} break; case 150: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} +{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} break; case 151: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy454 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy454,yymsp[-2].minor.yy454);} +{yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy590,yymsp[-2].minor.yy590);} break; case 152: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy203, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy203,yymsp[0].minor.yy454,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy563, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy563,yymsp[0].minor.yy590,0,0); } break; case 157: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-1].minor.yy454 = 0;} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-1].minor.yy590 = 0;} break; case 158: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy14); yymsp[-3].minor.yy454 = yymsp[-2].minor.yy454;} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy402); yymsp[-3].minor.yy590 = yymsp[-2].minor.yy590;} break; case 159: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy203, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy14,"set list"); - if( yymsp[-1].minor.yy203 ){ - SrcList *pFromClause = yymsp[-1].minor.yy203; + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy563, &yymsp[-4].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy402,"set list"); + if( yymsp[-1].minor.yy563 ){ + SrcList *pFromClause = yymsp[-1].minor.yy563; if( pFromClause->nSrc>1 ){ Select *pSubquery; Token as; @@ -183167,90 +181878,90 @@ static YYACTIONTYPE yy_reduce( as.z = 0; pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); } - yymsp[-5].minor.yy203 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy203, pFromClause); + yymsp[-5].minor.yy563 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy563, pFromClause); } - sqlite3Update(pParse,yymsp[-5].minor.yy203,yymsp[-2].minor.yy14,yymsp[0].minor.yy454,yymsp[-6].minor.yy144,0,0,0); + sqlite3Update(pParse,yymsp[-5].minor.yy563,yymsp[-2].minor.yy402,yymsp[0].minor.yy590,yymsp[-6].minor.yy502,0,0,0); } break; case 160: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy14, yymsp[0].minor.yy454); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy590); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1); } break; case 161: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy14 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy14, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); + yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); } break; case 162: /* setlist ::= nm EQ expr */ { - yylhsminor.yy14 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy454); - sqlite3ExprListSetName(pParse, yylhsminor.yy14, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy590); + sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy14 = yylhsminor.yy14; + yymsp[-2].minor.yy402 = yylhsminor.yy402; break; case 163: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy132, yymsp[0].minor.yy454); + yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy204, yymsp[0].minor.yy590); } break; case 164: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy555, yymsp[-2].minor.yy132, yymsp[-5].minor.yy144, yymsp[0].minor.yy122); + sqlite3Insert(pParse, yymsp[-3].minor.yy563, yymsp[-1].minor.yy637, yymsp[-2].minor.yy204, yymsp[-5].minor.yy502, yymsp[0].minor.yy403); } break; case 165: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ { - sqlite3Insert(pParse, yymsp[-4].minor.yy203, 0, yymsp[-3].minor.yy132, yymsp[-6].minor.yy144, 0); + sqlite3Insert(pParse, yymsp[-4].minor.yy563, 0, yymsp[-3].minor.yy204, yymsp[-6].minor.yy502, 0); } break; case 166: /* upsert ::= */ -{ yymsp[1].minor.yy122 = 0; } +{ yymsp[1].minor.yy403 = 0; } break; case 167: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy122 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy14); } +{ yymsp[-1].minor.yy403 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy402); } break; case 168: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy14,yymsp[-6].minor.yy454,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,yymsp[0].minor.yy122);} +{ yymsp[-11].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy402,yymsp[-6].minor.yy590,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,yymsp[0].minor.yy403);} break; case 169: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy122 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy14,yymsp[-3].minor.yy454,0,0,yymsp[0].minor.yy122); } +{ yymsp[-8].minor.yy403 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy402,yymsp[-3].minor.yy590,0,0,yymsp[0].minor.yy403); } break; case 170: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } +{ yymsp[-4].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } break; case 171: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy122 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454,0);} +{ yymsp[-7].minor.yy403 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590,0);} break; case 172: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy14);} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy402);} break; case 175: /* idlist_opt ::= */ -{yymsp[1].minor.yy132 = 0;} +{yymsp[1].minor.yy204 = 0;} break; case 176: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy132 = yymsp[-1].minor.yy132;} +{yymsp[-2].minor.yy204 = yymsp[-1].minor.yy204;} break; case 177: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy132 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy132,&yymsp[0].minor.yy0);} +{yymsp[-2].minor.yy204 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy204,&yymsp[0].minor.yy0);} break; case 178: /* idlist ::= nm */ -{yymsp[0].minor.yy132 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} +{yymsp[0].minor.yy204 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; case 179: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy454 = yymsp[-1].minor.yy454;} +{yymsp[-2].minor.yy590 = yymsp[-1].minor.yy590;} break; case 180: /* expr ::= ID|INDEXED|JOIN_KW */ -{yymsp[0].minor.yy454=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy590=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 181: /* expr ::= nm DOT nm */ { Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); - yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } - yymsp[-2].minor.yy454 = yylhsminor.yy454; + yymsp[-2].minor.yy590 = yylhsminor.yy590; break; case 182: /* expr ::= nm DOT nm DOT nm */ { @@ -183261,32 +181972,27 @@ static YYACTIONTYPE yy_reduce( if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, 0, temp1); } - yylhsminor.yy454 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy590 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } - yymsp[-4].minor.yy454 = yylhsminor.yy454; + yymsp[-4].minor.yy590 = yylhsminor.yy590; break; case 183: /* term ::= NULL|FLOAT|BLOB */ case 184: /* term ::= STRING */ yytestcase(yyruleno==184); -{yymsp[0].minor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 185: /* term ::= INTEGER */ { - int iValue; - if( sqlite3GetInt32(yymsp[0].minor.yy0.z, &iValue)==0 ){ - yylhsminor.yy454 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 0); - }else{ - yylhsminor.yy454 = sqlite3ExprInt32(pParse->db, iValue); - } - if( yylhsminor.yy454 ) yylhsminor.yy454->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); + yylhsminor.yy590 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + if( yylhsminor.yy590 ) yylhsminor.yy590->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); } - yymsp[0].minor.yy454 = yylhsminor.yy454; + yymsp[0].minor.yy590 = yylhsminor.yy590; break; case 186: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy454 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy454, n); + yymsp[0].minor.yy590 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy590, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers @@ -183295,80 +182001,80 @@ static YYACTIONTYPE yy_reduce( assert( t.n>=2 ); if( pParse->nested==0 ){ parserSyntaxError(pParse, &t); - yymsp[0].minor.yy454 = 0; + yymsp[0].minor.yy590 = 0; }else{ - yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable); + yymsp[0].minor.yy590 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy590 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy590->iTable); } } } break; case 187: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy454 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy454, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy590 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy590, &yymsp[0].minor.yy0, 1); } break; case 188: /* expr ::= CAST LP expr AS typetoken RP */ { - yymsp[-5].minor.yy454 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy454, yymsp[-3].minor.yy454, 0); + yymsp[-5].minor.yy590 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy590, yymsp[-3].minor.yy590, 0); } break; case 189: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy144); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502); } - yymsp[-4].minor.yy454 = yylhsminor.yy454; + yymsp[-4].minor.yy590 = yylhsminor.yy590; break; case 190: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy14, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy144); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-1].minor.yy14); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-4].minor.yy402, &yymsp[-7].minor.yy0, yymsp[-5].minor.yy502); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-1].minor.yy402); } - yymsp[-7].minor.yy454 = yylhsminor.yy454; + yymsp[-7].minor.yy590 = yylhsminor.yy590; break; case 191: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); } - yymsp[-3].minor.yy454 = yylhsminor.yy454; + yymsp[-3].minor.yy590 = yylhsminor.yy590; break; case 192: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy14, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy144); - sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy402, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy502); + sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); } - yymsp[-5].minor.yy454 = yylhsminor.yy454; + yymsp[-5].minor.yy590 = yylhsminor.yy590; break; case 193: /* expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy14, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy144); - sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); - sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy454, yymsp[-2].minor.yy14); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, yymsp[-5].minor.yy402, &yymsp[-8].minor.yy0, yymsp[-6].minor.yy502); + sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); + sqlite3ExprAddFunctionOrderBy(pParse, yylhsminor.yy590, yymsp[-2].minor.yy402); } - yymsp[-8].minor.yy454 = yylhsminor.yy454; + yymsp[-8].minor.yy590 = yylhsminor.yy590; break; case 194: /* expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy454, yymsp[0].minor.yy211); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); + sqlite3WindowAttach(pParse, yylhsminor.yy590, yymsp[0].minor.yy483); } - yymsp[-4].minor.yy454 = yylhsminor.yy454; + yymsp[-4].minor.yy590 = yylhsminor.yy590; break; case 195: /* term ::= CTIME_KW */ { - yylhsminor.yy454 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); } - yymsp[0].minor.yy454 = yylhsminor.yy454; + yymsp[0].minor.yy590 = yylhsminor.yy590; break; case 196: /* expr ::= LP nexprlist COMMA expr RP */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy454 ){ - yymsp[-4].minor.yy454->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy590 ){ + yymsp[-4].minor.yy590->x.pList = pList; if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy454->flags |= pList->a[0].pExpr->flags & EP_Propagate; + yymsp[-4].minor.yy590->flags |= pList->a[0].pExpr->flags & EP_Propagate; } }else{ sqlite3ExprListDelete(pParse->db, pList); @@ -183376,7 +182082,7 @@ static YYACTIONTYPE yy_reduce( } break; case 197: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy454=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} +{yymsp[-2].minor.yy590=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} break; case 198: /* expr ::= expr OR expr */ case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199); @@ -183385,7 +182091,7 @@ static YYACTIONTYPE yy_reduce( case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202); case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203); case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204); -{yymsp[-2].minor.yy454=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy454,yymsp[0].minor.yy454);} +{yymsp[-2].minor.yy590=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy590,yymsp[0].minor.yy590);} break; case 205: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} @@ -183395,11 +182101,11 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy454); - yymsp[-2].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy454, 0); - if( yymsp[-2].minor.yy454 ) yymsp[-2].minor.yy454->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy590); + yymsp[-2].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + if( bNot ) yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy590, 0); + if( yymsp[-2].minor.yy590 ) yymsp[-2].minor.yy590->flags |= EP_InfixFunc; } break; case 207: /* expr ::= expr likeop expr ESCAPE expr */ @@ -183407,87 +182113,91 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); - yymsp[-4].minor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); - if( yymsp[-4].minor.yy454 ) yymsp[-4].minor.yy454->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); + yymsp[-4].minor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); + if( bNot ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); + if( yymsp[-4].minor.yy590 ) yymsp[-4].minor.yy590->flags |= EP_InfixFunc; } break; case 208: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy454 = sqlite3PExprIsNull(pParse,yymsp[0].major,yymsp[-1].minor.yy454);} +{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy590,0);} break; case 209: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy454 = sqlite3PExprIsNull(pParse,TK_NOTNULL,yymsp[-2].minor.yy454);} +{yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy590,0);} break; case 210: /* expr ::= expr IS expr */ { - yymsp[-2].minor.yy454 = sqlite3PExprIs(pParse, TK_IS, yymsp[-2].minor.yy454, yymsp[0].minor.yy454); + yymsp[-2].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-2].minor.yy590, TK_ISNULL); } break; case 211: /* expr ::= expr IS NOT expr */ { - yymsp[-3].minor.yy454 = sqlite3PExprIs(pParse, TK_ISNOT, yymsp[-3].minor.yy454, yymsp[0].minor.yy454); + yymsp[-3].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-3].minor.yy590, TK_NOTNULL); } break; case 212: /* expr ::= expr IS NOT DISTINCT FROM expr */ { - yymsp[-5].minor.yy454 = sqlite3PExprIs(pParse, TK_IS, yymsp[-5].minor.yy454, yymsp[0].minor.yy454); + yymsp[-5].minor.yy590 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-5].minor.yy590, TK_ISNULL); } break; case 213: /* expr ::= expr IS DISTINCT FROM expr */ { - yymsp[-4].minor.yy454 = sqlite3PExprIs(pParse, TK_ISNOT, yymsp[-4].minor.yy454, yymsp[0].minor.yy454); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy590,yymsp[0].minor.yy590); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy590, yymsp[-4].minor.yy590, TK_NOTNULL); } break; case 214: /* expr ::= NOT expr */ case 215: /* expr ::= BITNOT expr */ yytestcase(yyruleno==215); -{yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy454, 0);/*A-overwrites-B*/} +{yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy590, 0);/*A-overwrites-B*/} break; case 216: /* expr ::= PLUS|MINUS expr */ { - Expr *p = yymsp[0].minor.yy454; + Expr *p = yymsp[0].minor.yy590; u8 op = yymsp[-1].major + (TK_UPLUS-TK_PLUS); assert( TK_UPLUS>TK_PLUS ); assert( TK_UMINUS == TK_MINUS + (TK_UPLUS - TK_PLUS) ); if( p && p->op==TK_UPLUS ){ p->op = op; - yymsp[-1].minor.yy454 = p; + yymsp[-1].minor.yy590 = p; }else{ - yymsp[-1].minor.yy454 = sqlite3PExpr(pParse, op, p, 0); + yymsp[-1].minor.yy590 = sqlite3PExpr(pParse, op, p, 0); /*A-overwrites-B*/ } } break; case 217: /* expr ::= expr PTR expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy454); - pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy454); - yylhsminor.yy454 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy590); + pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy590); + yylhsminor.yy590 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); } - yymsp[-2].minor.yy454 = yylhsminor.yy454; + yymsp[-2].minor.yy590 = yylhsminor.yy590; break; case 218: /* between_op ::= BETWEEN */ case 221: /* in_op ::= IN */ yytestcase(yyruleno==221); -{yymsp[0].minor.yy144 = 0;} +{yymsp[0].minor.yy502 = 0;} break; case 220: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy454); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy454, 0); - if( yymsp[-4].minor.yy454 ){ - yymsp[-4].minor.yy454->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy590); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy590, 0); + if( yymsp[-4].minor.yy590 ){ + yymsp[-4].minor.yy590->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } break; case 223: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy14==0 ){ + if( yymsp[-1].minor.yy402==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -183500,145 +182210,145 @@ static YYACTIONTYPE yy_reduce( ** it is or not) and if it is an aggregate, that could change the meaning ** of the whole query. */ - Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy144 ? "true" : "false"); + Expr *pB = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy502 ? "true" : "false"); if( pB ) sqlite3ExprIdToTrueFalse(pB); - if( !ExprHasProperty(yymsp[-4].minor.yy454, EP_HasFunc) ){ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy454); - yymsp[-4].minor.yy454 = pB; + if( !ExprHasProperty(yymsp[-4].minor.yy590, EP_HasFunc) ){ + sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy590); + yymsp[-4].minor.yy590 = pB; }else{ - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, yymsp[-3].minor.yy144 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_OR : TK_AND, pB, yymsp[-4].minor.yy590); } }else{ - Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr; - if( yymsp[-1].minor.yy14->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy454->op!=TK_VECTOR ){ - yymsp[-1].minor.yy14->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + Expr *pRHS = yymsp[-1].minor.yy402->a[0].pExpr; + if( yymsp[-1].minor.yy402->nExpr==1 && sqlite3ExprIsConstant(pParse,pRHS) && yymsp[-4].minor.yy590->op!=TK_VECTOR ){ + yymsp[-1].minor.yy402->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy454, pRHS); - }else if( yymsp[-1].minor.yy14->nExpr==1 && pRHS->op==TK_SELECT ){ - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pRHS->x.pSelect); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy590, pRHS); + }else if( yymsp[-1].minor.yy402->nExpr==1 && pRHS->op==TK_SELECT ){ + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pRHS->x.pSelect); pRHS->x.pSelect = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); }else{ - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - if( yymsp[-4].minor.yy454==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14); - }else if( yymsp[-4].minor.yy454->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy454->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy14); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + if( yymsp[-4].minor.yy590==0 ){ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402); + }else if( yymsp[-4].minor.yy590->pLeft->op==TK_VECTOR ){ + int nExpr = yymsp[-4].minor.yy590->pLeft->x.pList->nExpr; + Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy402); if( pSelectRHS ){ parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelectRHS); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelectRHS); } }else{ - yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy14; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy402; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); } } - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } } break; case 224: /* expr ::= LP select RP */ { - yymsp[-2].minor.yy454 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy454, yymsp[-1].minor.yy555); + yymsp[-2].minor.yy590 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy590, yymsp[-1].minor.yy637); } break; case 225: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, yymsp[-1].minor.yy555); - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, yymsp[-1].minor.yy637); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } break; case 226: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy14 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy14); - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy454, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy454, pSelect); - if( yymsp[-3].minor.yy144 ) yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy454, 0); + if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy590, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy590, pSelect); + if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy590, 0); } break; case 227: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy555); + p = yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy637); } break; case 228: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yymsp[-4].minor.yy454 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy454, 0); - if( yymsp[-4].minor.yy454 ){ - yymsp[-4].minor.yy454->x.pList = yymsp[-1].minor.yy454 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy454) : yymsp[-2].minor.yy14; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy454); + yymsp[-4].minor.yy590 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy590, 0); + if( yymsp[-4].minor.yy590 ){ + yymsp[-4].minor.yy590->x.pList = yymsp[-1].minor.yy590 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy590) : yymsp[-2].minor.yy402; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy590); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); } } break; case 229: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[-2].minor.yy454); - yymsp[-4].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, yymsp[0].minor.yy454); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy590); + yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy590); } break; case 230: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy454); - yymsp[-3].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy14, yymsp[0].minor.yy454); + yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy590); + yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy590); } break; case 235: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[0].minor.yy454);} +{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy590);} break; case 236: /* nexprlist ::= expr */ -{yymsp[0].minor.yy14 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy454); /*A-overwrites-Y*/} +{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy590); /*A-overwrites-Y*/} break; case 238: /* paren_exprlist ::= LP exprlist RP */ case 243: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==243); -{yymsp[-2].minor.yy14 = yymsp[-1].minor.yy14;} +{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;} break; case 239: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy14, yymsp[-10].minor.yy144, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy454, SQLITE_SO_ASC, yymsp[-8].minor.yy144, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy502, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy590, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF); if( IN_RENAME_OBJECT && pParse->pNewIndex ){ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); } } break; case 240: /* uniqueflag ::= UNIQUE */ - case 281: /* raisetype ::= ABORT */ yytestcase(yyruleno==281); -{yymsp[0].minor.yy144 = OE_Abort;} + case 282: /* raisetype ::= ABORT */ yytestcase(yyruleno==282); +{yymsp[0].minor.yy502 = OE_Abort;} break; case 241: /* uniqueflag ::= */ -{yymsp[1].minor.yy144 = OE_None;} +{yymsp[1].minor.yy502 = OE_None;} break; case 244: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy14 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy14, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); + yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); } break; case 245: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy14 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy144, yymsp[0].minor.yy144); /*A-overwrites-Y*/ + yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/ } break; case 248: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy203, yymsp[-1].minor.yy144);} +{sqlite3DropIndex(pParse, yymsp[0].minor.yy563, yymsp[-1].minor.yy502);} break; case 249: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy454);} +{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy590);} break; case 250: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy454);} +{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy590);} break; case 253: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} @@ -183660,12 +182370,12 @@ static YYACTIONTYPE yy_reduce( Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy427, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy319, &all); } break; case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy144, yymsp[-4].minor.yy286.a, yymsp[-4].minor.yy286.b, yymsp[-2].minor.yy203, yymsp[0].minor.yy454, yymsp[-10].minor.yy144, yymsp[-8].minor.yy144); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy28.a, yymsp[-4].minor.yy28.b, yymsp[-2].minor.yy563, yymsp[0].minor.yy590, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ #ifdef SQLITE_DEBUG assert( pParse->isCreate ); /* Set by createkw reduce action */ @@ -183674,439 +182384,421 @@ static YYACTIONTYPE yy_reduce( } break; case 262: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy144 = yymsp[0].major; /*A-overwrites-X*/ } +{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ } break; case 263: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy144 = TK_INSTEAD;} +{ yymsp[-1].minor.yy502 = TK_INSTEAD;} break; case 264: /* trigger_time ::= */ -{ yymsp[1].minor.yy144 = TK_BEFORE; } +{ yymsp[1].minor.yy502 = TK_BEFORE; } break; case 265: /* trigger_event ::= DELETE|INSERT */ case 266: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==266); -{yymsp[0].minor.yy286.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy286.b = 0;} +{yymsp[0].minor.yy28.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy28.b = 0;} break; case 267: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy286.a = TK_UPDATE; yymsp[-2].minor.yy286.b = yymsp[0].minor.yy132;} +{yymsp[-2].minor.yy28.a = TK_UPDATE; yymsp[-2].minor.yy28.b = yymsp[0].minor.yy204;} break; case 268: /* when_clause ::= */ - case 286: /* key_opt ::= */ yytestcase(yyruleno==286); -{ yymsp[1].minor.yy454 = 0; } + case 287: /* key_opt ::= */ yytestcase(yyruleno==287); +{ yymsp[1].minor.yy590 = 0; } break; case 269: /* when_clause ::= WHEN expr */ - case 287: /* key_opt ::= KEY expr */ yytestcase(yyruleno==287); -{ yymsp[-1].minor.yy454 = yymsp[0].minor.yy454; } + case 288: /* key_opt ::= KEY expr */ yytestcase(yyruleno==288); +{ yymsp[-1].minor.yy590 = yymsp[0].minor.yy590; } break; case 270: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - yymsp[-2].minor.yy427->pLast->pNext = yymsp[-1].minor.yy427; - yymsp[-2].minor.yy427->pLast = yymsp[-1].minor.yy427; + assert( yymsp[-2].minor.yy319!=0 ); + yymsp[-2].minor.yy319->pLast->pNext = yymsp[-1].minor.yy319; + yymsp[-2].minor.yy319->pLast = yymsp[-1].minor.yy319; } break; case 271: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - yymsp[-1].minor.yy427->pLast = yymsp[-1].minor.yy427; + assert( yymsp[-1].minor.yy319!=0 ); + yymsp[-1].minor.yy319->pLast = yymsp[-1].minor.yy319; } break; - case 272: /* tridxby ::= INDEXED BY nm */ + case 272: /* trnm ::= nm DOT nm */ +{ + yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; + sqlite3ErrorMsg(pParse, + "qualified table names are not allowed on INSERT, UPDATE, and DELETE " + "statements within triggers"); +} + break; + case 273: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 273: /* tridxby ::= NOT INDEXED */ + case 274: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 274: /* trigger_cmd ::= UPDATE orconf xfullname tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy427 = sqlite3TriggerUpdateStep(pParse, yymsp[-6].minor.yy203, yymsp[-2].minor.yy203, yymsp[-3].minor.yy14, yymsp[-1].minor.yy454, yymsp[-7].minor.yy144, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy168);} - yymsp[-8].minor.yy427 = yylhsminor.yy427; + case 275: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ +{yylhsminor.yy319 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy563, yymsp[-3].minor.yy402, yymsp[-1].minor.yy590, yymsp[-7].minor.yy502, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy342);} + yymsp[-8].minor.yy319 = yylhsminor.yy319; break; - case 275: /* trigger_cmd ::= scanpt insert_cmd INTO xfullname idlist_opt select upsert scanpt */ + case 276: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - yylhsminor.yy427 = sqlite3TriggerInsertStep(pParse,yymsp[-4].minor.yy203,yymsp[-3].minor.yy132,yymsp[-2].minor.yy555,yymsp[-6].minor.yy144,yymsp[-1].minor.yy122,yymsp[-7].minor.yy168,yymsp[0].minor.yy168);/*yylhsminor.yy427-overwrites-yymsp[-6].minor.yy144*/ + yylhsminor.yy319 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy204,yymsp[-2].minor.yy637,yymsp[-6].minor.yy502,yymsp[-1].minor.yy403,yymsp[-7].minor.yy342,yymsp[0].minor.yy342);/*yylhsminor.yy319-overwrites-yymsp[-6].minor.yy502*/ } - yymsp[-7].minor.yy427 = yylhsminor.yy427; + yymsp[-7].minor.yy319 = yylhsminor.yy319; break; - case 276: /* trigger_cmd ::= DELETE FROM xfullname tridxby where_opt scanpt */ -{yylhsminor.yy427 = sqlite3TriggerDeleteStep(pParse, yymsp[-3].minor.yy203, yymsp[-1].minor.yy454, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy168);} - yymsp[-5].minor.yy427 = yylhsminor.yy427; + case 277: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +{yylhsminor.yy319 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy590, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy342);} + yymsp[-5].minor.yy319 = yylhsminor.yy319; break; - case 277: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy427 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy555, yymsp[-2].minor.yy168, yymsp[0].minor.yy168); /*yylhsminor.yy427-overwrites-yymsp[-1].minor.yy555*/} - yymsp[-2].minor.yy427 = yylhsminor.yy427; + case 278: /* trigger_cmd ::= scanpt select scanpt */ +{yylhsminor.yy319 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy637, yymsp[-2].minor.yy342, yymsp[0].minor.yy342); /*yylhsminor.yy319-overwrites-yymsp[-1].minor.yy637*/} + yymsp[-2].minor.yy319 = yylhsminor.yy319; break; - case 278: /* expr ::= RAISE LP IGNORE RP */ + case 279: /* expr ::= RAISE LP IGNORE RP */ { - yymsp[-3].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy454 ){ - yymsp[-3].minor.yy454->affExpr = OE_Ignore; + yymsp[-3].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy590 ){ + yymsp[-3].minor.yy590->affExpr = OE_Ignore; } } break; - case 279: /* expr ::= RAISE LP raisetype COMMA expr RP */ + case 280: /* expr ::= RAISE LP raisetype COMMA expr RP */ { - yymsp[-5].minor.yy454 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy454, 0); - if( yymsp[-5].minor.yy454 ) { - yymsp[-5].minor.yy454->affExpr = (char)yymsp[-3].minor.yy144; + yymsp[-5].minor.yy590 = sqlite3PExpr(pParse, TK_RAISE, yymsp[-1].minor.yy590, 0); + if( yymsp[-5].minor.yy590 ) { + yymsp[-5].minor.yy590->affExpr = (char)yymsp[-3].minor.yy502; } } break; - case 280: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy144 = OE_Rollback;} + case 281: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy502 = OE_Rollback;} break; - case 282: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy144 = OE_Fail;} + case 283: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy502 = OE_Fail;} break; - case 283: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy203,yymsp[-1].minor.yy144); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy563,yymsp[-1].minor.yy502); } break; - case 284: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy454, yymsp[-1].minor.yy454, yymsp[0].minor.yy454); + sqlite3Attach(pParse, yymsp[-3].minor.yy590, yymsp[-1].minor.yy590, yymsp[0].minor.yy590); } break; - case 285: /* cmd ::= DETACH database_kw_opt expr */ + case 286: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy454); + sqlite3Detach(pParse, yymsp[0].minor.yy590); } break; - case 288: /* cmd ::= REINDEX */ + case 289: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 289: /* cmd ::= REINDEX nm dbnm */ + case 290: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 290: /* cmd ::= ANALYZE */ + case 291: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 291: /* cmd ::= ANALYZE nm dbnm */ + case 292: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 292: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 293: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy203,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy563,&yymsp[0].minor.yy0); } break; - case 293: /* cmd ::= alter_add carglist */ + case 294: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); -} - break; - case 294: /* alter_add ::= ALTER TABLE fullname ADD kwcolumn_opt nm typetoken */ -{ - disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[-4].minor.yy203); - sqlite3AddColumn(pParse, yymsp[-1].minor.yy0, yymsp[0].minor.yy0); - yymsp[-6].minor.yy0 = yymsp[-1].minor.yy0; } break; case 295: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ { - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0); -} - break; - case 296: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ -{ - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy203, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy563, &yymsp[0].minor.yy0); } break; - case 297: /* cmd ::= ALTER TABLE fullname DROP CONSTRAINT nm */ + case 296: /* add_column_fullname ::= fullname */ { - sqlite3AlterDropConstraint(pParse, yymsp[-3].minor.yy203, &yymsp[0].minor.yy0, 0); -} - break; - case 298: /* cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm DROP NOT NULL */ -{ - sqlite3AlterDropConstraint(pParse, yymsp[-6].minor.yy203, 0, &yymsp[-3].minor.yy0); -} - break; - case 299: /* cmd ::= ALTER TABLE fullname ALTER kwcolumn_opt nm SET NOT NULL onconf */ -{ - sqlite3AlterSetNotNull(pParse, yymsp[-7].minor.yy203, &yymsp[-4].minor.yy0, &yymsp[-2].minor.yy0); -} - break; - case 300: /* cmd ::= ALTER TABLE fullname ADD CONSTRAINT nm CHECK LP expr RP onconf */ -{ - sqlite3AlterAddConstraint(pParse, yymsp[-8].minor.yy203, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1)); + disableLookaside(pParse); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy563); } - yy_destructor(yypParser,219,&yymsp[-2].minor); break; - case 301: /* cmd ::= ALTER TABLE fullname ADD CHECK LP expr RP onconf */ + case 297: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ { - sqlite3AlterAddConstraint(pParse, yymsp[-6].minor.yy203, &yymsp[-4].minor.yy0, 0, yymsp[-3].minor.yy0.z+1, (yymsp[-1].minor.yy0.z-yymsp[-3].minor.yy0.z-1)); + sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy563, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } - yy_destructor(yypParser,219,&yymsp[-2].minor); break; - case 302: /* cmd ::= create_vtab */ + case 298: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 303: /* cmd ::= create_vtab LP vtabarglist RP */ + case 299: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 304: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 300: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy144); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502); } break; - case 305: /* vtabarg ::= */ + case 301: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 306: /* vtabargtoken ::= ANY */ - case 307: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==307); - case 308: /* lp ::= LP */ yytestcase(yyruleno==308); + case 302: /* vtabargtoken ::= ANY */ + case 303: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==303); + case 304: /* lp ::= LP */ yytestcase(yyruleno==304); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 309: /* with ::= WITH wqlist */ - case 310: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==310); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); } + case 305: /* with ::= WITH wqlist */ + case 306: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==306); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy125, 1); } break; - case 311: /* wqas ::= AS */ -{yymsp[0].minor.yy462 = M10d_Any;} + case 307: /* wqas ::= AS */ +{yymsp[0].minor.yy444 = M10d_Any;} break; - case 312: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy462 = M10d_Yes;} + case 308: /* wqas ::= AS MATERIALIZED */ +{yymsp[-1].minor.yy444 = M10d_Yes;} break; - case 313: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy462 = M10d_No;} + case 309: /* wqas ::= AS NOT MATERIALIZED */ +{yymsp[-2].minor.yy444 = M10d_No;} break; - case 314: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ + case 310: /* wqitem ::= withnm eidlist_opt wqas LP select RP */ { - yymsp[-5].minor.yy67 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy14, yymsp[-1].minor.yy555, yymsp[-3].minor.yy462); /*A-overwrites-X*/ + yymsp[-5].minor.yy361 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy637, yymsp[-3].minor.yy444); /*A-overwrites-X*/ } break; - case 315: /* withnm ::= nm */ + case 311: /* withnm ::= nm */ {pParse->bHasWith = 1;} break; - case 316: /* wqlist ::= wqitem */ + case 312: /* wqlist ::= wqitem */ { - yymsp[0].minor.yy59 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy67); /*A-overwrites-X*/ + yymsp[0].minor.yy125 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy361); /*A-overwrites-X*/ } break; - case 317: /* wqlist ::= wqlist COMMA wqitem */ + case 313: /* wqlist ::= wqlist COMMA wqitem */ { - yymsp[-2].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy59, yymsp[0].minor.yy67); + yymsp[-2].minor.yy125 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy125, yymsp[0].minor.yy361); } break; - case 318: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + case 314: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { - assert( yymsp[0].minor.yy211!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy211); - yymsp[0].minor.yy211->pNextWin = yymsp[-2].minor.yy211; - yylhsminor.yy211 = yymsp[0].minor.yy211; + assert( yymsp[0].minor.yy483!=0 ); + sqlite3WindowChain(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy483); + yymsp[0].minor.yy483->pNextWin = yymsp[-2].minor.yy483; + yylhsminor.yy483 = yymsp[0].minor.yy483; } - yymsp[-2].minor.yy211 = yylhsminor.yy211; + yymsp[-2].minor.yy483 = yylhsminor.yy483; break; - case 319: /* windowdefn ::= nm AS LP window RP */ + case 315: /* windowdefn ::= nm AS LP window RP */ { - if( ALWAYS(yymsp[-1].minor.yy211) ){ - yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); + if( ALWAYS(yymsp[-1].minor.yy483) ){ + yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); } - yylhsminor.yy211 = yymsp[-1].minor.yy211; + yylhsminor.yy483 = yymsp[-1].minor.yy483; } - yymsp[-4].minor.yy211 = yylhsminor.yy211; + yymsp[-4].minor.yy483 = yylhsminor.yy483; break; - case 320: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + case 316: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { - yymsp[-4].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, 0); + yymsp[-4].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, 0); } break; - case 321: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + case 317: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { - yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, yymsp[-2].minor.yy14, yymsp[-1].minor.yy14, &yymsp[-5].minor.yy0); + yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, yymsp[-2].minor.yy402, yymsp[-1].minor.yy402, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy211 = yylhsminor.yy211; + yymsp[-5].minor.yy483 = yylhsminor.yy483; break; - case 322: /* window ::= ORDER BY sortlist frame_opt */ + case 318: /* window ::= ORDER BY sortlist frame_opt */ { - yymsp[-3].minor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, 0); + yymsp[-3].minor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, 0); } break; - case 323: /* window ::= nm ORDER BY sortlist frame_opt */ + case 319: /* window ::= nm ORDER BY sortlist frame_opt */ { - yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, yymsp[-1].minor.yy14, &yymsp[-4].minor.yy0); + yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy211 = yylhsminor.yy211; + yymsp[-4].minor.yy483 = yylhsminor.yy483; break; - case 324: /* window ::= nm frame_opt */ + case 320: /* window ::= nm frame_opt */ { - yylhsminor.yy211 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy211, 0, 0, &yymsp[-1].minor.yy0); + yylhsminor.yy483 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy483, 0, 0, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy211 = yylhsminor.yy211; + yymsp[-1].minor.yy483 = yylhsminor.yy483; break; - case 325: /* frame_opt ::= */ + case 321: /* frame_opt ::= */ { - yymsp[1].minor.yy211 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); + yymsp[1].minor.yy483 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); } break; - case 326: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + case 322: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ { - yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy144, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy462); + yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy502, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy444); } - yymsp[-2].minor.yy211 = yylhsminor.yy211; + yymsp[-2].minor.yy483 = yylhsminor.yy483; break; - case 327: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + case 323: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ { - yylhsminor.yy211 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy144, yymsp[-3].minor.yy509.eType, yymsp[-3].minor.yy509.pExpr, yymsp[-1].minor.yy509.eType, yymsp[-1].minor.yy509.pExpr, yymsp[0].minor.yy462); + yylhsminor.yy483 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy502, yymsp[-3].minor.yy205.eType, yymsp[-3].minor.yy205.pExpr, yymsp[-1].minor.yy205.eType, yymsp[-1].minor.yy205.pExpr, yymsp[0].minor.yy444); } - yymsp[-5].minor.yy211 = yylhsminor.yy211; + yymsp[-5].minor.yy483 = yylhsminor.yy483; break; - case 329: /* frame_bound_s ::= frame_bound */ - case 331: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==331); -{yylhsminor.yy509 = yymsp[0].minor.yy509;} - yymsp[0].minor.yy509 = yylhsminor.yy509; + case 325: /* frame_bound_s ::= frame_bound */ + case 327: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==327); +{yylhsminor.yy205 = yymsp[0].minor.yy205;} + yymsp[0].minor.yy205 = yylhsminor.yy205; break; - case 330: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 332: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==332); - case 334: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==334); -{yylhsminor.yy509.eType = yymsp[-1].major; yylhsminor.yy509.pExpr = 0;} - yymsp[-1].minor.yy509 = yylhsminor.yy509; + case 326: /* frame_bound_s ::= UNBOUNDED PRECEDING */ + case 328: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==328); + case 330: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==330); +{yylhsminor.yy205.eType = yymsp[-1].major; yylhsminor.yy205.pExpr = 0;} + yymsp[-1].minor.yy205 = yylhsminor.yy205; break; - case 333: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy509.eType = yymsp[0].major; yylhsminor.yy509.pExpr = yymsp[-1].minor.yy454;} - yymsp[-1].minor.yy509 = yylhsminor.yy509; + case 329: /* frame_bound ::= expr PRECEDING|FOLLOWING */ +{yylhsminor.yy205.eType = yymsp[0].major; yylhsminor.yy205.pExpr = yymsp[-1].minor.yy590;} + yymsp[-1].minor.yy205 = yylhsminor.yy205; break; - case 335: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy462 = 0;} + case 331: /* frame_exclude_opt ::= */ +{yymsp[1].minor.yy444 = 0;} break; - case 336: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy462 = yymsp[0].minor.yy462;} + case 332: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ +{yymsp[-1].minor.yy444 = yymsp[0].minor.yy444;} break; - case 337: /* frame_exclude ::= NO OTHERS */ - case 338: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==338); -{yymsp[-1].minor.yy462 = yymsp[-1].major; /*A-overwrites-X*/} + case 333: /* frame_exclude ::= NO OTHERS */ + case 334: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==334); +{yymsp[-1].minor.yy444 = yymsp[-1].major; /*A-overwrites-X*/} break; - case 339: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy462 = yymsp[0].major; /*A-overwrites-X*/} + case 335: /* frame_exclude ::= GROUP|TIES */ +{yymsp[0].minor.yy444 = yymsp[0].major; /*A-overwrites-X*/} break; - case 340: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy211 = yymsp[0].minor.yy211; } + case 336: /* window_clause ::= WINDOW windowdefn_list */ +{ yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; } break; - case 341: /* filter_over ::= filter_clause over_clause */ + case 337: /* filter_over ::= filter_clause over_clause */ { - if( yymsp[0].minor.yy211 ){ - yymsp[0].minor.yy211->pFilter = yymsp[-1].minor.yy454; + if( yymsp[0].minor.yy483 ){ + yymsp[0].minor.yy483->pFilter = yymsp[-1].minor.yy590; }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy454); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy590); } - yylhsminor.yy211 = yymsp[0].minor.yy211; + yylhsminor.yy483 = yymsp[0].minor.yy483; } - yymsp[-1].minor.yy211 = yylhsminor.yy211; + yymsp[-1].minor.yy483 = yylhsminor.yy483; break; - case 342: /* filter_over ::= over_clause */ + case 338: /* filter_over ::= over_clause */ { - yylhsminor.yy211 = yymsp[0].minor.yy211; + yylhsminor.yy483 = yymsp[0].minor.yy483; } - yymsp[0].minor.yy211 = yylhsminor.yy211; + yymsp[0].minor.yy483 = yylhsminor.yy483; break; - case 343: /* filter_over ::= filter_clause */ + case 339: /* filter_over ::= filter_clause */ { - yylhsminor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy211 ){ - yylhsminor.yy211->eFrmType = TK_FILTER; - yylhsminor.yy211->pFilter = yymsp[0].minor.yy454; + yylhsminor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yylhsminor.yy483 ){ + yylhsminor.yy483->eFrmType = TK_FILTER; + yylhsminor.yy483->pFilter = yymsp[0].minor.yy590; }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy454); + sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy590); } } - yymsp[0].minor.yy211 = yylhsminor.yy211; + yymsp[0].minor.yy483 = yylhsminor.yy483; break; - case 344: /* over_clause ::= OVER LP window RP */ + case 340: /* over_clause ::= OVER LP window RP */ { - yymsp[-3].minor.yy211 = yymsp[-1].minor.yy211; - assert( yymsp[-3].minor.yy211!=0 ); + yymsp[-3].minor.yy483 = yymsp[-1].minor.yy483; + assert( yymsp[-3].minor.yy483!=0 ); } break; - case 345: /* over_clause ::= OVER nm */ + case 341: /* over_clause ::= OVER nm */ { - yymsp[-1].minor.yy211 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy211 ){ - yymsp[-1].minor.yy211->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); + yymsp[-1].minor.yy483 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yymsp[-1].minor.yy483 ){ + yymsp[-1].minor.yy483->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); } } break; - case 346: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy454 = yymsp[-1].minor.yy454; } + case 342: /* filter_clause ::= FILTER LP WHERE expr RP */ +{ yymsp[-4].minor.yy590 = yymsp[-1].minor.yy590; } break; - case 347: /* term ::= QNUMBER */ + case 343: /* term ::= QNUMBER */ { - yylhsminor.yy454=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); - sqlite3DequoteNumber(pParse, yylhsminor.yy454); + yylhsminor.yy590=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); + sqlite3DequoteNumber(pParse, yylhsminor.yy590); } - yymsp[0].minor.yy454 = yylhsminor.yy454; + yymsp[0].minor.yy590 = yylhsminor.yy590; break; default: - /* (348) input ::= cmdlist */ yytestcase(yyruleno==348); - /* (349) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==349); - /* (350) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=350); - /* (351) ecmd ::= SEMI */ yytestcase(yyruleno==351); - /* (352) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==352); - /* (353) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=353); - /* (354) trans_opt ::= */ yytestcase(yyruleno==354); - /* (355) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==355); - /* (356) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==356); - /* (357) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==357); - /* (358) savepoint_opt ::= */ yytestcase(yyruleno==358); - /* (359) cmd ::= create_table create_table_args */ yytestcase(yyruleno==359); - /* (360) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=360); - /* (361) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==361); - /* (362) columnlist ::= columnname carglist */ yytestcase(yyruleno==362); - /* (363) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==363); - /* (364) nm ::= STRING */ yytestcase(yyruleno==364); - /* (365) typetoken ::= typename */ yytestcase(yyruleno==365); - /* (366) typename ::= ID|STRING */ yytestcase(yyruleno==366); - /* (367) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=367); - /* (368) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=368); - /* (369) carglist ::= carglist ccons */ yytestcase(yyruleno==369); - /* (370) carglist ::= */ yytestcase(yyruleno==370); - /* (371) ccons ::= NULL onconf */ yytestcase(yyruleno==371); - /* (372) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==372); - /* (373) ccons ::= AS generated */ yytestcase(yyruleno==373); - /* (374) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==374); - /* (375) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==375); - /* (376) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=376); - /* (377) tconscomma ::= */ yytestcase(yyruleno==377); - /* (378) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=378); - /* (379) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=379); - /* (380) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=380); - /* (381) oneselect ::= values */ yytestcase(yyruleno==381); - /* (382) sclp ::= selcollist COMMA */ yytestcase(yyruleno==382); - /* (383) as ::= ID|STRING */ yytestcase(yyruleno==383); - /* (384) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=384); - /* (385) returning ::= */ yytestcase(yyruleno==385); - /* (386) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=386); - /* (387) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==387); - /* (388) case_operand ::= expr */ yytestcase(yyruleno==388); - /* (389) exprlist ::= nexprlist */ yytestcase(yyruleno==389); - /* (390) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=390); - /* (391) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=391); - /* (392) nmnum ::= ON */ yytestcase(yyruleno==392); - /* (393) nmnum ::= DELETE */ yytestcase(yyruleno==393); - /* (394) nmnum ::= DEFAULT */ yytestcase(yyruleno==394); - /* (395) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==395); - /* (396) foreach_clause ::= */ yytestcase(yyruleno==396); - /* (397) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==397); - /* (398) tridxby ::= */ yytestcase(yyruleno==398); - /* (399) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==399); - /* (400) database_kw_opt ::= */ yytestcase(yyruleno==400); - /* (401) kwcolumn_opt ::= */ yytestcase(yyruleno==401); - /* (402) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==402); - /* (403) vtabarglist ::= vtabarg */ yytestcase(yyruleno==403); - /* (404) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==404); - /* (405) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==405); - /* (406) anylist ::= */ yytestcase(yyruleno==406); - /* (407) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==407); - /* (408) anylist ::= anylist ANY */ yytestcase(yyruleno==408); - /* (409) with ::= */ yytestcase(yyruleno==409); - /* (410) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=410); - /* (411) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=411); + /* (344) input ::= cmdlist */ yytestcase(yyruleno==344); + /* (345) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==345); + /* (346) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=346); + /* (347) ecmd ::= SEMI */ yytestcase(yyruleno==347); + /* (348) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==348); + /* (349) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=349); + /* (350) trans_opt ::= */ yytestcase(yyruleno==350); + /* (351) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==351); + /* (352) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==352); + /* (353) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==353); + /* (354) savepoint_opt ::= */ yytestcase(yyruleno==354); + /* (355) cmd ::= create_table create_table_args */ yytestcase(yyruleno==355); + /* (356) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=356); + /* (357) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==357); + /* (358) columnlist ::= columnname carglist */ yytestcase(yyruleno==358); + /* (359) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==359); + /* (360) nm ::= STRING */ yytestcase(yyruleno==360); + /* (361) typetoken ::= typename */ yytestcase(yyruleno==361); + /* (362) typename ::= ID|STRING */ yytestcase(yyruleno==362); + /* (363) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=363); + /* (364) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=364); + /* (365) carglist ::= carglist ccons */ yytestcase(yyruleno==365); + /* (366) carglist ::= */ yytestcase(yyruleno==366); + /* (367) ccons ::= NULL onconf */ yytestcase(yyruleno==367); + /* (368) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==368); + /* (369) ccons ::= AS generated */ yytestcase(yyruleno==369); + /* (370) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==370); + /* (371) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==371); + /* (372) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=372); + /* (373) tconscomma ::= */ yytestcase(yyruleno==373); + /* (374) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=374); + /* (375) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=375); + /* (376) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=376); + /* (377) oneselect ::= values */ yytestcase(yyruleno==377); + /* (378) sclp ::= selcollist COMMA */ yytestcase(yyruleno==378); + /* (379) as ::= ID|STRING */ yytestcase(yyruleno==379); + /* (380) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=380); + /* (381) returning ::= */ yytestcase(yyruleno==381); + /* (382) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=382); + /* (383) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==383); + /* (384) case_operand ::= expr */ yytestcase(yyruleno==384); + /* (385) exprlist ::= nexprlist */ yytestcase(yyruleno==385); + /* (386) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=386); + /* (387) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=387); + /* (388) nmnum ::= ON */ yytestcase(yyruleno==388); + /* (389) nmnum ::= DELETE */ yytestcase(yyruleno==389); + /* (390) nmnum ::= DEFAULT */ yytestcase(yyruleno==390); + /* (391) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==391); + /* (392) foreach_clause ::= */ yytestcase(yyruleno==392); + /* (393) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==393); + /* (394) trnm ::= nm */ yytestcase(yyruleno==394); + /* (395) tridxby ::= */ yytestcase(yyruleno==395); + /* (396) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==396); + /* (397) database_kw_opt ::= */ yytestcase(yyruleno==397); + /* (398) kwcolumn_opt ::= */ yytestcase(yyruleno==398); + /* (399) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==399); + /* (400) vtabarglist ::= vtabarg */ yytestcase(yyruleno==400); + /* (401) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==401); + /* (402) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==402); + /* (403) anylist ::= */ yytestcase(yyruleno==403); + /* (404) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==404); + /* (405) anylist ::= anylist ANY */ yytestcase(yyruleno==405); + /* (406) with ::= */ yytestcase(yyruleno==406); + /* (407) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=407); + /* (408) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=408); break; /********** End reduce actions ************************************************/ }; @@ -184885,8 +183577,8 @@ static const unsigned char aKWCode[148] = {0, /* 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 i64 keywordCode(const char *z, i64 n, int *pType){ - i64 i, j; +static int keywordCode(const char *z, int n, int *pType){ + int i, j; const char *zKW; assert( n>=2 ); i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127; @@ -185440,7 +184132,7 @@ SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *z, int *tokenType){ } case CC_DOLLAR: case CC_VARALPHA: { - i64 n = 0; + int n = 0; testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' ); testcase( z[0]=='#' ); *tokenType = TK_VARIABLE; @@ -185536,7 +184228,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ - i64 mxSqlLen; /* Max length of an SQL string */ + int mxSqlLen; /* Max length of an SQL string */ Parse *pParentParse = 0; /* Outer parse context, if any */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ @@ -187192,14 +185884,6 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ rc = setupLookaside(db, pBuf, sz, cnt); break; } - case SQLITE_DBCONFIG_FP_DIGITS: { - int nIn = va_arg(ap, int); - int *pOut = va_arg(ap, int*); - if( nIn>3 && nIn<24 ) db->nFpDigit = (u8)nIn; - if( pOut ) *pOut = db->nFpDigit; - rc = SQLITE_OK; - break; - } default: { static const struct { int op; /* The opcode */ @@ -188755,9 +187439,6 @@ SQLITE_API void *sqlite3_wal_hook( sqlite3_mutex_leave(db->mutex); return pRet; #else - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(xCallback); - UNUSED_PARAMETER(pArg); return 0; #endif } @@ -188773,11 +187454,6 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( int *pnCkpt /* OUT: Total number of frames checkpointed */ ){ #ifdef SQLITE_OMIT_WAL - UNUSED_PARAMETER(db); - UNUSED_PARAMETER(zDb); - UNUSED_PARAMETER(eMode); - UNUSED_PARAMETER(pnLog); - UNUSED_PARAMETER(pnCkpt); return SQLITE_OK; #else int rc; /* Return code */ @@ -188791,12 +187467,11 @@ SQLITE_API int sqlite3_wal_checkpoint_v2( if( pnLog ) *pnLog = -1; if( pnCkpt ) *pnCkpt = -1; - assert( SQLITE_CHECKPOINT_NOOP==-1 ); assert( SQLITE_CHECKPOINT_PASSIVE==0 ); assert( SQLITE_CHECKPOINT_FULL==1 ); assert( SQLITE_CHECKPOINT_RESTART==2 ); assert( SQLITE_CHECKPOINT_TRUNCATE==3 ); - if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ + if( eModeSQLITE_CHECKPOINT_TRUNCATE ){ /* EVIDENCE-OF: R-03996-12088 The M parameter must be a valid checkpoint ** mode: */ return SQLITE_MISUSE_BKPT; @@ -189160,7 +187835,6 @@ static const int aHardLimit[] = { SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */ SQLITE_MAX_TRIGGER_DEPTH, SQLITE_MAX_WORKER_THREADS, - SQLITE_MAX_PARSER_DEPTH, }; /* @@ -189175,9 +187849,6 @@ static const int aHardLimit[] = { #if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH # error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH #endif -#if SQLITE_MAX_SQL_LENGTH>2147482624 /* 1024 less than 2^31 */ -# error SQLITE_MAX_SQL_LENGTH must not be greater than 2147482624 -#endif #if SQLITE_MAX_COMPOUND_SELECT<2 # error SQLITE_MAX_COMPOUND_SELECT must be at least 2 #endif @@ -189233,7 +187904,6 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ assert( aHardLimit[SQLITE_LIMIT_SQL_LENGTH]==SQLITE_MAX_SQL_LENGTH ); assert( aHardLimit[SQLITE_LIMIT_COLUMN]==SQLITE_MAX_COLUMN ); assert( aHardLimit[SQLITE_LIMIT_EXPR_DEPTH]==SQLITE_MAX_EXPR_DEPTH ); - assert( aHardLimit[SQLITE_LIMIT_PARSER_DEPTH]==SQLITE_MAX_PARSER_DEPTH ); assert( aHardLimit[SQLITE_LIMIT_COMPOUND_SELECT]==SQLITE_MAX_COMPOUND_SELECT); assert( aHardLimit[SQLITE_LIMIT_VDBE_OP]==SQLITE_MAX_VDBE_OP ); assert( aHardLimit[SQLITE_LIMIT_FUNCTION_ARG]==SQLITE_MAX_FUNCTION_ARG ); @@ -189243,7 +187913,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ assert( aHardLimit[SQLITE_LIMIT_VARIABLE_NUMBER]==SQLITE_MAX_VARIABLE_NUMBER); assert( aHardLimit[SQLITE_LIMIT_TRIGGER_DEPTH]==SQLITE_MAX_TRIGGER_DEPTH ); assert( aHardLimit[SQLITE_LIMIT_WORKER_THREADS]==SQLITE_MAX_WORKER_THREADS ); - assert( SQLITE_LIMIT_PARSER_DEPTH==(SQLITE_N_LIMIT-1) ); + assert( SQLITE_LIMIT_WORKER_THREADS==(SQLITE_N_LIMIT-1) ); if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ @@ -189607,7 +188277,7 @@ static int openDatabase( db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; if( isThreadsafe -#if defined(SQLITE_THREAD_MISUSE_WARNINGS) +#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS || sqlite3GlobalConfig.bCoreMutex #endif ){ @@ -189628,7 +188298,6 @@ static int openDatabase( db->aDb = db->aDbStatic; db->lookaside.bDisable = 1; db->lookaside.sz = 0; - db->nFpDigit = 17; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); @@ -190074,12 +188743,6 @@ SQLITE_API int sqlite3_collation_needed16( */ SQLITE_API void *sqlite3_get_clientdata(sqlite3 *db, const char *zName){ DbClientData *p; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !zName || !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return 0; - } -#endif sqlite3_mutex_enter(db->mutex); for(p=db->pDbData; p; p=p->pNext){ if( strcmp(p->zName, zName)==0 ){ @@ -191153,7 +189816,6 @@ SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){ } SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){ #ifdef SQLITE_OMIT_WAL - UNUSED_PARAMETER(zFilename); return 0; #else zFilename = sqlite3_filename_journal(zFilename); @@ -192925,15 +191587,6 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \ ) -SQLITE_PRIVATE int sqlite3Fts3PrepareStmt( - Fts3Table *p, /* Prepare for this connection */ - const char *zSql, /* SQL to prepare */ - int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */ - int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */ - sqlite3_stmt **pp /* OUT: Prepared statement */ -); - - /* fts3.c */ SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); @@ -194541,7 +193194,9 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); if( !zSql ) return SQLITE_NOMEM; p->bLock++; - rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt); + rc = sqlite3_prepare_v3( + p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 + ); p->bLock--; sqlite3_free(zSql); } @@ -196116,7 +194771,9 @@ static int fts3FilterMethod( } if( zSql ){ p->bLock++; - rc = sqlite3Fts3PrepareStmt(p, zSql, 1, 1, &pCsr->pStmt); + rc = sqlite3_prepare_v3( + p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0 + ); p->bLock--; sqlite3_free(zSql); }else{ @@ -196739,7 +195396,6 @@ static int fts3IntegrityMethod( UNUSED_PARAMETER(isQuick); rc = sqlite3Fts3IntegrityCheck(p, &bOk); - assert( pVtab->zErrMsg==0 || rc!=SQLITE_OK ); assert( rc!=SQLITE_CORRUPT_VTAB ); if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){ *pzErr = sqlite3_mprintf("unable to validate the inverted index for" @@ -203177,9 +201833,9 @@ typedef struct SegmentWriter SegmentWriter; ** incrementally. See function fts3PendingListAppend() for details. */ struct PendingList { - sqlite3_int64 nData; + int nData; char *aData; - sqlite3_int64 nSpace; + int nSpace; sqlite3_int64 iLastDocid; sqlite3_int64 iLastCol; sqlite3_int64 iLastPos; @@ -203352,24 +202008,6 @@ struct SegmentNode { #define SQL_UPDATE_LEVEL_IDX 38 #define SQL_UPDATE_LEVEL 39 -/* -** Wrapper around sqlite3_prepare_v3() to ensure that SQLITE_PREPARE_FROM_DDL -** is always set. -*/ -SQLITE_PRIVATE int sqlite3Fts3PrepareStmt( - Fts3Table *p, /* Prepare for this connection */ - const char *zSql, /* SQL to prepare */ - int bPersist, /* True to set SQLITE_PREPARE_PERSISTENT */ - int bAllowVtab, /* True to omit SQLITE_PREPARE_NO_VTAB */ - sqlite3_stmt **pp /* OUT: Prepared statement */ -){ - int f = SQLITE_PREPARE_FROM_DDL - |((bAllowVtab==0) ? SQLITE_PREPARE_NO_VTAB : 0) - |(bPersist ? SQLITE_PREPARE_PERSISTENT : 0); - - return sqlite3_prepare_v3(p->db, zSql, -1, f, pp, NULL); -} - /* ** This function is used to obtain an SQLite prepared statement handle ** for the statement identified by the second argument. If successful, @@ -203495,12 +202133,12 @@ static int fts3SqlStmt( pStmt = p->aStmt[eStmt]; if( !pStmt ){ - int bAllowVtab = 0; + int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB; char *zSql; if( eStmt==SQL_CONTENT_INSERT ){ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist); }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){ - bAllowVtab = 1; + f &= ~SQLITE_PREPARE_NO_VTAB; zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist); }else{ zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName); @@ -203508,7 +202146,7 @@ static int fts3SqlStmt( if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3Fts3PrepareStmt(p, zSql, 1, bAllowVtab, &pStmt); + rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL); sqlite3_free(zSql); assert( rc==SQLITE_OK || pStmt==0 ); p->aStmt[eStmt] = pStmt; @@ -203857,9 +202495,7 @@ static int fts3PendingTermsAddOne( pList = (PendingList *)fts3HashFind(pHash, zToken, nToken); if( pList ){ - assert( (i64)pList->nData+(i64)nToken+(i64)sizeof(Fts3HashElem) - <= (i64)p->nPendingData ); - p->nPendingData -= (int)(pList->nData + nToken + sizeof(Fts3HashElem)); + p->nPendingData -= (pList->nData + nToken + sizeof(Fts3HashElem)); } if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){ if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){ @@ -203872,9 +202508,7 @@ static int fts3PendingTermsAddOne( } } if( rc==SQLITE_OK ){ - assert( (i64)p->nPendingData + pList->nData + nToken - + sizeof(Fts3HashElem) <= 0x3fffffff ); - p->nPendingData += (int)(pList->nData + nToken + sizeof(Fts3HashElem)); + p->nPendingData += (pList->nData + nToken + sizeof(Fts3HashElem)); } return rc; } @@ -206675,7 +205309,7 @@ static int fts3DoRebuild(Fts3Table *p){ if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); } @@ -208428,7 +207062,7 @@ SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){ if( !zSql ){ rc = SQLITE_NOMEM; }else{ - rc = sqlite3Fts3PrepareStmt(p, zSql, 0, 1, &pStmt); + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); } @@ -208558,7 +207192,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ v = atoi(&zVal[9]); if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v; rc = SQLITE_OK; - }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 11) ){ + }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){ v = atoi(&zVal[11]); if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v; rc = SQLITE_OK; @@ -211833,10 +210467,7 @@ struct JsonString { #define JSON_SQL 0x02 /* Result is always SQL */ #define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ #define JSON_ISSET 0x04 /* json_set(), not json_insert() */ -#define JSON_AINS 0x08 /* json_array_insert(), not json_insert() */ -#define JSON_BLOB 0x10 /* Use the BLOB output format */ - -#define JSON_INSERT_TYPE(X) (((X)&0xC)>>2) +#define JSON_BLOB 0x08 /* Use the BLOB output format */ /* A parsed JSON value. Lifecycle: @@ -211882,7 +210513,6 @@ struct JsonParse { #define JEDIT_REPL 2 /* Overwrite if exists */ #define JEDIT_INS 3 /* Insert if not exists */ #define JEDIT_SET 4 /* Insert or overwrite */ -#define JEDIT_AINS 5 /* array_insert() */ /* ** Maximum nesting depth of JSON for this implementation. @@ -214379,8 +213009,7 @@ static int jsonLabelCompare( */ #define JSON_LOOKUP_ERROR 0xffffffff #define JSON_LOOKUP_NOTFOUND 0xfffffffe -#define JSON_LOOKUP_NOTARRAY 0xfffffffd -#define JSON_LOOKUP_PATHERROR 0xfffffffc +#define JSON_LOOKUP_PATHERROR 0xfffffffd #define JSON_LOOKUP_ISERROR(x) ((x)>=JSON_LOOKUP_PATHERROR) /* Forward declaration */ @@ -214409,7 +213038,7 @@ static u32 jsonLookupStep(JsonParse*,u32,const char*,u32); static u32 jsonCreateEditSubstructure( JsonParse *pParse, /* The original JSONB that is being edited */ JsonParse *pIns, /* Populate this with the blob data to insert */ - const char *zTail /* Tail of the path that determines substructure */ + const char *zTail /* Tail of the path that determins substructure */ ){ static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT }; int rc; @@ -214444,9 +213073,9 @@ static u32 jsonCreateEditSubstructure( ** Return one of the JSON_LOOKUP error codes if problems are seen. ** ** This routine will also modify the blob. If pParse->eEdit is one of -** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, JEDIT_SET, or JEDIT_AINS, then changes -** might be made to the selected value. If an edit is performed, then the -** return value does not necessarily point to the select element. If an edit +** JEDIT_DEL, JEDIT_REPL, JEDIT_INS, or JEDIT_SET, then changes might be +** made to the selected value. If an edit is performed, then the return +** value does not necessarily point to the select element. If an edit ** is performed, the return value is only useful for detecting error ** conditions. */ @@ -214472,13 +213101,6 @@ static u32 jsonLookupStep( jsonBlobEdit(pParse, iRoot, sz, 0, 0); }else if( pParse->eEdit==JEDIT_INS ){ /* Already exists, so json_insert() is a no-op */ - }else if( pParse->eEdit==JEDIT_AINS ){ - /* json_array_insert() */ - if( zPath[-1]!=']' ){ - return JSON_LOOKUP_NOTARRAY; - }else{ - jsonBlobEdit(pParse, iRoot, 0, pParse->aIns, pParse->nIns); - } }else{ /* json_set() or json_replace() */ jsonBlobEdit(pParse, iRoot, sz, pParse->aIns, pParse->nIns); @@ -214550,10 +213172,6 @@ static u32 jsonLookupStep( JsonParse ix; /* Header of the label to be inserted */ testcase( pParse->eEdit==JEDIT_INS ); testcase( pParse->eEdit==JEDIT_SET ); - testcase( pParse->eEdit==JEDIT_AINS ); - if( pParse->eEdit==JEDIT_AINS && sqlite3_strglob("*]",&zPath[i])!=0 ){ - return JSON_LOOKUP_NOTARRAY; - } memset(&ix, 0, sizeof(ix)); ix.db = pParse->db; jsonBlobAppendNode(&ix, rawKey?JSONB_TEXTRAW:JSONB_TEXT5, nKey, 0); @@ -214581,32 +213199,28 @@ static u32 jsonLookupStep( return rc; } }else if( zPath[0]=='[' ){ - u64 kk = 0; x = pParse->aBlob[iRoot] & 0x0f; if( x!=JSONB_ARRAY ) return JSON_LOOKUP_NOTFOUND; n = jsonbPayloadSize(pParse, iRoot, &sz); + k = 0; i = 1; while( sqlite3Isdigit(zPath[i]) ){ - if( kk<0xffffffff ) kk = kk*10 + zPath[i] - '0'; - /* ^^^^^^^^^^--- Allow kk to be bigger than any JSON array so that - ** we get NOTFOUND instead of PATHERROR, without overflowing kk. */ + k = k*10 + zPath[i] - '0'; i++; } if( i<2 || zPath[i]!=']' ){ if( zPath[1]=='#' ){ - kk = jsonbArrayCount(pParse, iRoot); + k = jsonbArrayCount(pParse, iRoot); i = 2; if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ - u64 nn = 0; + unsigned int nn = 0; i = 3; do{ - if( nn<0xffffffff ) nn = nn*10 + zPath[i] - '0'; - /* ^^^^^^^^^^--- Allow nn to be bigger than any JSON array to - ** get NOTFOUND instead of PATHERROR, without overflowing nn. */ + nn = nn*10 + zPath[i] - '0'; i++; }while( sqlite3Isdigit(zPath[i]) ); - if( nn>kk ) return JSON_LOOKUP_NOTFOUND; - kk -= nn; + if( nn>k ) return JSON_LOOKUP_NOTFOUND; + k -= nn; } if( zPath[i]!=']' ){ return JSON_LOOKUP_PATHERROR; @@ -214618,22 +213232,21 @@ static u32 jsonLookupStep( j = iRoot+n; iEnd = j+sz; while( jdelta ) jsonAfterEditSizeAdjust(pParse, iRoot); return rc; } - kk--; + k--; n = jsonbPayloadSize(pParse, j, &sz); if( n==0 ) return JSON_LOOKUP_ERROR; j += n+sz; } if( j>iEnd ) return JSON_LOOKUP_ERROR; - if( kk>0 ) return JSON_LOOKUP_NOTFOUND; + if( k>0 ) return JSON_LOOKUP_NOTFOUND; if( pParse->eEdit>=JEDIT_INS ){ JsonParse v; testcase( pParse->eEdit==JEDIT_INS ); - testcase( pParse->eEdit==JEDIT_AINS ); testcase( pParse->eEdit==JEDIT_SET ); rc = jsonCreateEditSubstructure(pParse, &v, &zPath[i+1]); if( !JSON_LOOKUP_ISERROR(rc) @@ -214771,7 +213384,7 @@ static void jsonReturnFromBlob( to_double: z = sqlite3DbStrNDup(db, (const char*)&pParse->aBlob[i+n], (int)sz); if( z==0 ) goto returnfromblob_oom; - rc = sqlite3AtoF(z, &r); + rc = sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); sqlite3DbFree(db, z); if( rc<=0 ) goto returnfromblob_malformed; sqlite3_result_double(pCtx, r); @@ -214958,15 +213571,9 @@ static int jsonFunctionArgToBlob( */ static char *jsonBadPathError( sqlite3_context *ctx, /* The function call containing the error */ - const char *zPath, /* The path with the problem */ - int rc /* Maybe JSON_LOOKUP_NOTARRAY */ + const char *zPath /* The path with the problem */ ){ - char *zMsg; - if( rc==(int)JSON_LOOKUP_NOTARRAY ){ - zMsg = sqlite3_mprintf("not an array element: %Q", zPath); - }else{ - zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); - } + char *zMsg = sqlite3_mprintf("bad JSON path: %Q", zPath); if( ctx==0 ) return zMsg; if( zMsg ){ sqlite3_result_error(ctx, zMsg, -1); @@ -214983,13 +213590,13 @@ static char *jsonBadPathError( ** and return the result. ** ** The specific operation is determined by eEdit, which can be one -** of JEDIT_INS, JEDIT_REPL, JEDIT_SET, or JEDIT_AINS. +** of JEDIT_INS, JEDIT_REPL, or JEDIT_SET. */ static void jsonInsertIntoBlob( sqlite3_context *ctx, int argc, sqlite3_value **argv, - int eEdit /* JEDIT_INS, JEDIT_REPL, JEDIT_SET, JEDIT_AINS */ + int eEdit /* JEDIT_INS, JEDIT_REPL, or JEDIT_SET */ ){ int i; u32 rc = 0; @@ -215041,7 +213648,7 @@ static void jsonInsertIntoBlob( if( rc==JSON_LOOKUP_ERROR ){ sqlite3_result_error(ctx, "malformed JSON", -1); }else{ - jsonBadPathError(ctx, zPath, rc); + jsonBadPathError(ctx, zPath); } return; } @@ -215483,7 +214090,7 @@ static void jsonArrayLengthFunc( if( i==JSON_LOOKUP_NOTFOUND ){ /* no-op */ }else if( i==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); }else{ sqlite3_result_error(ctx, "malformed JSON", -1); } @@ -215588,7 +214195,7 @@ static void jsonExtractFunc( j = jsonLookupStep(p, 0, jx.zBuf, 0); jsonStringReset(&jx); }else{ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); goto json_extract_error; } if( jnBlob ){ @@ -215623,7 +214230,7 @@ static void jsonExtractFunc( sqlite3_result_error(ctx, "malformed JSON", -1); goto json_extract_error; }else{ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); goto json_extract_error; } } @@ -215952,7 +214559,7 @@ static void jsonRemoveFunc( if( rc==JSON_LOOKUP_NOTFOUND ){ continue; /* No-op */ }else if( rc==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath, rc); + jsonBadPathError(ctx, zPath); }else{ sqlite3_result_error(ctx, "malformed JSON", -1); } @@ -215964,7 +214571,7 @@ static void jsonRemoveFunc( return; json_remove_patherror: - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); json_remove_done: jsonParseFree(p); @@ -216008,18 +214615,16 @@ static void jsonSetFunc( int argc, sqlite3_value **argv ){ + int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); - int eInsType = JSON_INSERT_TYPE(flags); - static const char *azInsType[] = { "insert", "set", "array_insert" }; - static const u8 aEditType[] = { JEDIT_INS, JEDIT_SET, JEDIT_AINS }; + int bIsSet = (flags&JSON_ISSET)!=0; if( argc<1 ) return; - assert( eInsType>=0 && eInsType<=2 ); if( (argc&1)==0 ) { - jsonWrongNumArgs(ctx, azInsType[eInsType]); + jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); return; } - jsonInsertIntoBlob(ctx, argc, argv, aEditType[eInsType]); + jsonInsertIntoBlob(ctx, argc, argv, bIsSet ? JEDIT_SET : JEDIT_INS); } /* @@ -216044,7 +214649,7 @@ static void jsonTypeFunc( zPath = (const char*)sqlite3_value_text(argv[1]); if( zPath==0 ) goto json_type_done; if( zPath[0]!='$' ){ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); goto json_type_done; } i = jsonLookupStep(p, 0, zPath+1, 0); @@ -216052,7 +214657,7 @@ static void jsonTypeFunc( if( i==JSON_LOOKUP_NOTFOUND ){ /* no-op */ }else if( i==JSON_LOOKUP_PATHERROR ){ - jsonBadPathError(ctx, zPath, 0); + jsonBadPathError(ctx, zPath); }else{ sqlite3_result_error(ctx, "malformed JSON", -1); } @@ -216308,11 +214913,12 @@ static void jsonArrayStep( } static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ JsonString *pStr; - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ + int flags; pStr->pCtx = ctx; jsonAppendChar(pStr, ']'); + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); if( pStr->eErr ){ jsonReturnString(pStr, 0, 0); return; @@ -216333,9 +214939,6 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); jsonStringTrimOneChar(pStr); } - }else if( flags & JSON_BLOB ){ - static const u8 emptyArray = 0x0b; - sqlite3_result_blob(ctx, &emptyArray, 1, SQLITE_STATIC); }else{ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); } @@ -216432,11 +215035,12 @@ static void jsonObjectStep( } static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ JsonString *pStr; - int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ + int flags; jsonAppendChar(pStr, '}'); pStr->pCtx = ctx; + flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); if( pStr->eErr ){ jsonReturnString(pStr, 0, 0); return; @@ -216457,9 +215061,6 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); jsonStringTrimOneChar(pStr); } - }else if( flags & JSON_BLOB ){ - static const unsigned char emptyObject = 0x0c; - sqlite3_result_blob(ctx, &emptyObject, 1, SQLITE_STATIC); }else{ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); } @@ -216960,7 +215561,7 @@ static int jsonEachFilter( if( zRoot==0 ) return SQLITE_OK; if( zRoot[0]!='$' ){ sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0); + cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } @@ -216978,7 +215579,7 @@ static int jsonEachFilter( return SQLITE_OK; } sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot, 0); + cur->pVtab->zErrMsg = jsonBadPathError(0, zRoot); jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } @@ -217068,8 +215669,6 @@ SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc), JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc), JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc), - JFUNCTION(json_array_insert, -1,1,1, 1,0,JSON_AINS, jsonSetFunc), - JFUNCTION(jsonb_array_insert,-1,1,0, 1,1,JSON_AINS, jsonSetFunc), JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc), JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc), JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc), @@ -221650,7 +220249,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ /* The sqlite3AtoF() routine is much much faster than atof(), if it ** is available */ double r; - (void)sqlite3AtoF((const char*)p->z, &r); + (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); *pVal = r; #else *pVal = (GeoCoord)atof((const char*)p->z); @@ -227235,8 +225834,8 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ /* If necessary, grow the pIter->aIdxCol[] array */ if( iIdxCol==nIdxAlloc ){ - RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc64( - pIter->aIdxCol, nIdxAlloc*sizeof(RbuSpan) + 16*sizeof(RbuSpan) + RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc( + pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan) ); if( aIdxCol==0 ){ rc = SQLITE_NOMEM; @@ -231909,7 +230508,6 @@ struct carray_bind { int nData; /* Number of elements */ int mFlags; /* Control flags */ void (*xDel)(void*); /* Destructor for aData */ - void *pDel; /* Alternative argument to xDel() */ }; @@ -232242,7 +230840,7 @@ static sqlite3_module carrayModule = { static void carrayBindDel(void *pPtr){ carray_bind *p = (carray_bind*)pPtr; if( p->xDel!=SQLITE_STATIC ){ - p->xDel(p->pDel); + p->xDel(p->aData); } sqlite3_free(p); } @@ -232250,26 +230848,14 @@ static void carrayBindDel(void *pPtr){ /* ** Invoke this interface in order to bind to the single-argument ** version of CARRAY(). -** -** pStmt The prepared statement to which to bind -** idx The index of the parameter of pStmt to which to bind -** aData The data to be bound -** nData The number of elements in aData -** mFlags One of SQLITE_CARRAY_xxxx indicating datatype of aData -** xDestroy Destructor for pDestroy or aData if pDestroy==NULL. -** pDestroy Invoke xDestroy on this pointer if not NULL -** -** The destructor is called pDestroy if pDestroy!=NULL, or against -** aData if pDestroy==NULL. */ -SQLITE_API int sqlite3_carray_bind_v2( +SQLITE_API int sqlite3_carray_bind( sqlite3_stmt *pStmt, int idx, void *aData, int nData, int mFlags, - void (*xDestroy)(void*), - void *pDestroy + void (*xDestroy)(void*) ){ carray_bind *pNew = 0; int i; @@ -232346,38 +230932,20 @@ SQLITE_API int sqlite3_carray_bind_v2( memcpy(pNew->aData, aData, sz); } pNew->xDel = sqlite3_free; - pNew->pDel = pNew->aData; }else{ pNew->aData = aData; pNew->xDel = xDestroy; - pNew->pDel = pDestroy; } return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel); carray_bind_error: if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){ - xDestroy(pDestroy); + xDestroy(aData); } sqlite3_free(pNew); return rc; } -/* -** Invoke this interface in order to bind to the single-argument -** version of CARRAY(). Same as sqlite3_carray_bind_v2() with the -** pDestroy parameter set to NULL. -*/ -SQLITE_API int sqlite3_carray_bind( - sqlite3_stmt *pStmt, - int idx, - void *aData, - int nData, - int mFlags, - void (*xDestroy)(void*) -){ - return sqlite3_carray_bind_v2(pStmt,idx,aData,nData,mFlags,xDestroy,aData); -} - /* ** Invoke this routine to register the carray() function. */ @@ -232740,20 +231308,6 @@ static int sessionVarintGet(const u8 *aBuf, int *piVal){ return getVarint32(aBuf, *piVal); } -/* -** Read a varint value from buffer aBuf[], size nBuf bytes, into *piVal. -** Return the number of bytes read. -*/ -static int sessionVarintGetSafe(const u8 *aBuf, int nBuf, int *piVal){ - u8 aCopy[5]; - const u8 *aRead = aBuf; - if( nBuf<5 ){ - memcpy(aCopy, aBuf, nBuf); - aRead = aCopy; - } - return getVarint32(aRead, *piVal); -} - /* Load an unaligned and unsigned 32-bit integer */ #define SESSION_UINT32(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3]) @@ -233048,10 +231602,14 @@ static unsigned int sessionChangeHash( int isPK = pTab->abPK[i]; if( bPkOnly && isPK==0 ) continue; + /* It is not possible for eType to be SQLITE_NULL here. The session + ** module does not record changes for rows with NULL values stored in + ** primary key columns. */ assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT || eType==SQLITE_TEXT || eType==SQLITE_BLOB || eType==SQLITE_NULL || eType==0 ); + assert( !isPK || (eType!=0 && eType!=SQLITE_NULL) ); if( isPK ){ a++; @@ -233059,16 +231617,12 @@ static unsigned int sessionChangeHash( if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ h = sessionHashAppendI64(h, sessionGetI64(a)); a += 8; - }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ + }else{ int n; a += sessionVarintGet(a, &n); h = sessionHashAppendBlob(h, n, a); a += n; } - /* It should not be possible for eType to be SQLITE_NULL or 0x00 here, - ** as the session module does not record changes for rows with NULL - ** values stored in primary key columns. But a corrupt changesets - ** may contain such a value. */ }else{ a += sessionSerialLen(a); } @@ -235477,13 +234031,10 @@ static int sessionGenerateChangeset( } if( pSession->rc ) return pSession->rc; + rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); + if( rc!=SQLITE_OK ) return rc; sqlite3_mutex_enter(sqlite3_db_mutex(db)); - rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); - if( rc!=SQLITE_OK ){ - sqlite3_mutex_leave(sqlite3_db_mutex(db)); - return rc; - } for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ @@ -235966,8 +234517,7 @@ static int sessionReadRecord( u8 *aVal = &pIn->aData[pIn->iNext]; if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ int nByte; - int nRem = pIn->nData - pIn->iNext; - pIn->iNext += sessionVarintGetSafe(aVal, nRem, &nByte); + pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); if( rc==SQLITE_OK ){ if( nByte<0 || nByte>pIn->nData-pIn->iNext ){ @@ -236020,8 +234570,7 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ - int nBuf = pIn->nData - pIn->iNext; - nRead += sessionVarintGetSafe(&pIn->aData[pIn->iNext], nBuf, &nCol); + nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); /* The hard upper limit for the number of columns in an SQLite ** database table is, according to sqliteLimit.h, 32676. So ** consider any table-header that purports to have more than 65536 @@ -236041,15 +234590,8 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ while( (pIn->iNext + nRead)nData && pIn->aData[pIn->iNext + nRead] ){ nRead++; } - - /* Break out of the loop if if the nul-terminator byte has been found. - ** Otherwise, read some more input data and keep seeking. If there is - ** no more input data, consider the changeset corrupt. */ if( (pIn->iNext + nRead)nData ) break; rc = sessionInputBuffer(pIn, nRead + 100); - if( rc==SQLITE_OK && (pIn->iNext + nRead)>=pIn->nData ){ - rc = SQLITE_CORRUPT_BKPT; - } } *pnByte = nRead+1; return rc; @@ -236181,10 +234723,10 @@ static int sessionChangesetNextOne( memset(p->apValue, 0, sizeof(sqlite3_value*)*p->nCol*2); } - /* Make sure the buffer contains at least 2 bytes of input data, or all - ** remaining data if there are less than 2 bytes available. This is - ** sufficient either for the 'T' or 'P' byte that begins a new table, - ** or for the "op" and "bIndirect" single bytes otherwise. */ + /* Make sure the buffer contains at least 10 bytes of input data, or all + ** remaining data if there are less than 10 bytes available. This is + ** sufficient either for the 'T' or 'P' byte and the varint that follows + ** it, or for the two single byte values otherwise. */ p->rc = sessionInputBuffer(&p->in, 2); if( p->rc!=SQLITE_OK ) return p->rc; @@ -236214,13 +234756,11 @@ static int sessionChangesetNextOne( return (p->rc = SQLITE_CORRUPT_BKPT); } - if( (op!=SQLITE_UPDATE && op!=SQLITE_DELETE && op!=SQLITE_INSERT) - || (p->in.iNext>=p->in.nData) - ){ - return (p->rc = SQLITE_CORRUPT_BKPT); - } p->op = op; p->bIndirect = p->in.aData[p->in.iNext++]; + if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ + return (p->rc = SQLITE_CORRUPT_BKPT); + } if( paRec ){ int nVal; /* Number of values to buffer */ @@ -241108,22 +239648,14 @@ typedef union { #define sqlite3Fts5ParserARG_PARAM ,pParse #define sqlite3Fts5ParserARG_FETCH Fts5Parse *pParse=fts5yypParser->pParse; #define sqlite3Fts5ParserARG_STORE fts5yypParser->pParse=pParse; -#undef fts5YYREALLOC #define fts5YYREALLOC realloc -#undef fts5YYFREE #define fts5YYFREE free -#undef fts5YYDYNSTACK #define fts5YYDYNSTACK 0 -#undef fts5YYSIZELIMIT -#define sqlite3Fts5ParserCTX(P) 0 #define sqlite3Fts5ParserCTX_SDECL #define sqlite3Fts5ParserCTX_PDECL #define sqlite3Fts5ParserCTX_PARAM #define sqlite3Fts5ParserCTX_FETCH #define sqlite3Fts5ParserCTX_STORE -#undef fts5YYERRORSYMBOL -#undef fts5YYERRSYMDT -#undef fts5YYFALLBACK #define fts5YYNSTATE 35 #define fts5YYNRULE 28 #define fts5YYNRULE_WITH_ACTION 28 @@ -241448,24 +239980,15 @@ static int fts5yyGrowStack(fts5yyParser *p){ int newSize; int idx; fts5yyStackEntry *pNew; -#ifdef fts5YYSIZELIMIT - int nLimit = fts5YYSIZELIMIT(sqlite3Fts5ParserCTX(p)); -#endif newSize = oldSize*2 + 100; -#ifdef fts5YYSIZELIMIT - if( newSize>nLimit ){ - newSize = nLimit; - if( newSize<=oldSize ) return 1; - } -#endif idx = (int)(p->fts5yytos - p->fts5yystack); if( p->fts5yystack==p->fts5yystk0 ){ - pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0]), sqlite3Fts5ParserCTX(p)); + pNew = fts5YYREALLOC(0, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; memcpy(pNew, p->fts5yystack, oldSize*sizeof(pNew[0])); }else{ - pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0]), sqlite3Fts5ParserCTX(p)); + pNew = fts5YYREALLOC(p->fts5yystack, newSize*sizeof(pNew[0])); if( pNew==0 ) return 1; } p->fts5yystack = pNew; @@ -241645,9 +240168,7 @@ static void sqlite3Fts5ParserFinalize(void *p){ } #if fts5YYGROWABLESTACK - if( pParser->fts5yystack!=pParser->fts5yystk0 ){ - fts5YYFREE(pParser->fts5yystack, sqlite3Fts5ParserCTX(pParser)); - } + if( pParser->fts5yystack!=pParser->fts5yystk0 ) fts5YYFREE(pParser->fts5yystack); #endif } @@ -242929,7 +241450,7 @@ static void fts5SnippetFunction( iBestCol = (iCol>=0 ? iCol : 0); nPhrase = pApi->xPhraseCount(pFts); - aSeen = sqlite3_malloc64(nPhrase); + aSeen = sqlite3_malloc(nPhrase); if( aSeen==0 ){ rc = SQLITE_NOMEM; } @@ -243584,7 +242105,7 @@ static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){ if( nIn<0 ){ nIn = (int)strlen(pIn); } - zRet = (char*)sqlite3_malloc64((i64)nIn+1); + zRet = (char*)sqlite3_malloc(nIn+1); if( zRet ){ memcpy(zRet, pIn, nIn); zRet[nIn] = '\0'; @@ -244284,7 +242805,7 @@ static int sqlite3Fts5ConfigParse( sqlite3_int64 nByte; int bUnindexed = 0; /* True if there are one or more UNINDEXED */ - *ppOut = pRet = (Fts5Config*)sqlite3_malloc64(sizeof(Fts5Config)); + *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config)); if( pRet==0 ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(Fts5Config)); pRet->pGlobal = pGlobal; @@ -244832,6 +243353,8 @@ static void sqlite3Fts5ConfigErrmsg(Fts5Config *pConfig, const char *zFmt, ...){ va_end(ap); } + + /* ** 2014 May 31 ** @@ -245148,7 +243671,7 @@ static int sqlite3Fts5ExprNew( assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 ); if( sParse.rc==SQLITE_OK ){ - *ppNew = pNew = sqlite3_malloc64(sizeof(Fts5Expr)); + *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); if( pNew==0 ){ sParse.rc = SQLITE_NOMEM; sqlite3Fts5ParseNodeFree(sParse.pExpr); @@ -245300,7 +243823,7 @@ static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ p2->pRoot = 0; if( sParse.rc==SQLITE_OK ){ - Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc64( + Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc( p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*) ); if( ap==0 ){ @@ -248212,7 +246735,7 @@ static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte int rc = SQLITE_OK; Fts5Hash *pNew; - *ppNew = pNew = (Fts5Hash*)sqlite3_malloc64(sizeof(Fts5Hash)); + *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash)); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -250805,7 +249328,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){ /* If necessary, grow the pIter->aRowidOffset[] array. */ if( iRowidOffset>=pIter->nRowidOffset ){ - i64 nNew = pIter->nRowidOffset + 8; + int nNew = pIter->nRowidOffset + 8; int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int)); if( aNew==0 ){ p->rc = SQLITE_NOMEM; @@ -254111,31 +252634,31 @@ static void fts5DoSecureDelete( ** is another term following it on this page. So the subsequent term ** needs to be moved to replace the term associated with the entry ** being removed. */ - u64 nPrefix = 0; - u64 nSuffix = 0; - u64 nPrefix2 = 0; - u64 nSuffix2 = 0; + int nPrefix = 0; + int nSuffix = 0; + int nPrefix2 = 0; + int nSuffix2 = 0; iDelKeyOff = iNextOff; - iNextOff += fts5GetVarint(&aPg[iNextOff], &nPrefix2); - iNextOff += fts5GetVarint(&aPg[iNextOff], &nSuffix2); + iNextOff += fts5GetVarint32(&aPg[iNextOff], nPrefix2); + iNextOff += fts5GetVarint32(&aPg[iNextOff], nSuffix2); if( iKey!=1 ){ - iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nPrefix); + iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nPrefix); } - iKeyOff += fts5GetVarint(&aPg[iKeyOff], &nSuffix); + iKeyOff += fts5GetVarint32(&aPg[iKeyOff], nSuffix); nPrefix = MIN(nPrefix, nPrefix2); nSuffix = (nPrefix2 + nSuffix2) - nPrefix; - if( (iKeyOff+nSuffix)>(u64)iPgIdx || (iNextOff+nSuffix2)>(u64)iPgIdx ){ + if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){ FTS5_CORRUPT_IDX(p); }else{ if( iKey!=1 ){ iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix); } iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix); - if( nPrefix2>(u64)pSeg->term.n ){ + if( nPrefix2>pSeg->term.n ){ FTS5_CORRUPT_IDX(p); }else if( nPrefix2>nPrefix ){ memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix); @@ -254166,7 +252689,7 @@ static void fts5DoSecureDelete( u8 *aTermIdx = &pTerm->p[pTerm->szLeaf]; int nTermIdx = pTerm->nn - pTerm->szLeaf; int iTermIdx = 0; - i64 iTermOff = 0; + int iTermOff = 0; while( 1 ){ u32 iVal = 0; @@ -254177,15 +252700,12 @@ static void fts5DoSecureDelete( } nTermIdx = iTermIdx; - if( iTermOff>pTerm->szLeaf ){ - FTS5_CORRUPT_IDX(p); - }else{ - memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx); - fts5PutU16(&pTerm->p[2], iTermOff); - fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx); - if( nTermIdx==0 ){ - fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno); - } + memmove(&pTerm->p[iTermOff], &pTerm->p[pTerm->szLeaf], nTermIdx); + fts5PutU16(&pTerm->p[2], iTermOff); + + fts5DataWrite(p, iId, pTerm->p, iTermOff+nTermIdx); + if( nTermIdx==0 ){ + fts5SecureDeleteIdxEntry(p, iSegid, pSeg->iTermLeafPgno); } } fts5DataRelease(pTerm); @@ -254208,9 +252728,7 @@ static void fts5DoSecureDelete( int iPrevKeyOut = 0; int iKeyIn = 0; - if( nMove>0 ){ - memmove(&aPg[iOff], &aPg[iNextOff], nMove); - } + memmove(&aPg[iOff], &aPg[iNextOff], nMove); iPgIdx -= nShift; nPg = iPgIdx; fts5PutU16(&aPg[2], iPgIdx); @@ -255130,16 +253648,16 @@ struct Fts5TokenDataMap { ** aMap[] variables. */ struct Fts5TokenDataIter { - i64 nMapAlloc; /* Allocated size of aMap[] in entries */ - i64 nMap; /* Number of valid entries in aMap[] */ + int nMapAlloc; /* Allocated size of aMap[] in entries */ + int nMap; /* Number of valid entries in aMap[] */ Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */ /* The following are used for prefix-queries only. */ Fts5Buffer terms; /* The following are used for other full-token tokendata queries only. */ - i64 nIter; - i64 nIterAlloc; + int nIter; + int nIterAlloc; Fts5PoslistReader *aPoslistReader; int *aPoslistToIter; Fts5Iter *apIter[FLEXARRAY]; @@ -255195,11 +253713,11 @@ static void fts5TokendataIterAppendMap( ){ if( p->rc==SQLITE_OK ){ if( pT->nMap==pT->nMapAlloc ){ - i64 nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64; - i64 nAlloc = nNew * sizeof(Fts5TokenDataMap); + int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64; + int nAlloc = nNew * sizeof(Fts5TokenDataMap); Fts5TokenDataMap *aNew; - aNew = (Fts5TokenDataMap*)sqlite3_realloc64(pT->aMap, nAlloc); + aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc); if( aNew==0 ){ p->rc = SQLITE_NOMEM; return; @@ -255225,7 +253743,7 @@ static void fts5TokendataIterAppendMap( */ static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){ Fts5TokenDataMap *aTmp = 0; - i64 nByte = pT->nMap * sizeof(Fts5TokenDataMap); + int nByte = pT->nMap * sizeof(Fts5TokenDataMap); aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte); if( aTmp ){ @@ -255759,10 +254277,9 @@ static Fts5TokenDataIter *fts5AppendTokendataIter( if( p->rc==SQLITE_OK ){ if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){ - i64 nAlloc = pIn ? pIn->nIterAlloc*2 : 16; - i64 nByte = SZ_FTS5TOKENDATAITER(nAlloc+1); - Fts5TokenDataIter *pNew; - pNew = (Fts5TokenDataIter*)sqlite3_realloc64(pIn, nByte); + int nAlloc = pIn ? pIn->nIterAlloc*2 : 16; + int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1); + Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte); if( pNew==0 ){ p->rc = SQLITE_NOMEM; @@ -255859,8 +254376,8 @@ static void fts5IterSetOutputsTokendata(Fts5Iter *pIter){ /* Ensure the token-mapping is large enough */ if( eDetail==FTS5_DETAIL_FULL && pT->nMapAlloc<(pT->nMap + nByte) ){ - i64 nNew = (pT->nMapAlloc + nByte) * 2; - Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc64( + int nNew = (pT->nMapAlloc + nByte) * 2; + Fts5TokenDataMap *aNew = (Fts5TokenDataMap*)sqlite3_realloc( pT->aMap, nNew*sizeof(Fts5TokenDataMap) ); if( aNew==0 ){ @@ -258889,7 +257406,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ return SQLITE_ERROR; } - idxStr = (char*)sqlite3_malloc64((i64)pInfo->nConstraint * 8 + 1); + idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1); if( idxStr==0 ) return SQLITE_NOMEM; pInfo->idxStr = idxStr; pInfo->needToFreeIdxStr = 1; @@ -260339,7 +258856,6 @@ static int fts5UpdateMethod( } update_out: - sqlite3Fts5IndexCloseReader(pTab->p.pIndex); pTab->p.pConfig->pzErrmsg = 0; return rc; } @@ -261857,7 +260373,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2026-03-13 10:38:09 737ae4a34738ffa0c3ff7f9bb18df914dd1cad163f28fd6b6e114a344fe6d618", -1, SQLITE_TRANSIENT); } /* @@ -262021,7 +260537,7 @@ static int fts5Init(sqlite3 *db){ int rc; Fts5Global *pGlobal = 0; - pGlobal = (Fts5Global*)sqlite3_malloc64(sizeof(Fts5Global)); + pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global)); if( pGlobal==0 ){ rc = SQLITE_NOMEM; }else{ @@ -263737,7 +262253,7 @@ static int fts5AsciiCreate( if( nArg%2 ){ rc = SQLITE_ERROR; }else{ - p = sqlite3_malloc64(sizeof(AsciiTokenizer)); + p = sqlite3_malloc(sizeof(AsciiTokenizer)); if( p==0 ){ rc = SQLITE_NOMEM; }else{ @@ -264032,7 +262548,7 @@ static int fts5UnicodeCreate( if( nArg%2 ){ rc = SQLITE_ERROR; }else{ - p = (Unicode61Tokenizer*)sqlite3_malloc64(sizeof(Unicode61Tokenizer)); + p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); if( p ){ const char *zCat = "L* N* Co"; int i; @@ -264255,7 +262771,7 @@ static int fts5PorterCreate( zBase = azArg[0]; } - pRet = (PorterTokenizer*)sqlite3_malloc64(sizeof(PorterTokenizer)); + pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer)); if( pRet ){ memset(pRet, 0, sizeof(PorterTokenizer)); rc = pApi->xFindTokenizer_v2(pApi, zBase, &pUserdata, &pV2); @@ -264962,7 +263478,7 @@ static int fts5TriCreate( rc = SQLITE_ERROR; }else{ int i; - pNew = (TrigramTokenizer*)sqlite3_malloc64(sizeof(*pNew)); + pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew)); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -266948,7 +265464,7 @@ static int fts5VocabFilterMethod( const char *zCopy = (const char *)sqlite3_value_text(pLe); if( zCopy==0 ) zCopy = ""; pCsr->nLeTerm = sqlite3_value_bytes(pLe); - pCsr->zLeTerm = sqlite3_malloc64((i64)pCsr->nLeTerm+1); + pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1); if( pCsr->zLeTerm==0 ){ rc = SQLITE_NOMEM; }else{ diff --git a/deps/sqlite/sqlite3.h b/deps/sqlite/sqlite3.h index 33856750dd35a9..302f0f5b1698d1 100644 --- a/deps/sqlite/sqlite3.h +++ b/deps/sqlite/sqlite3.h @@ -146,12 +146,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.52.0" -#define SQLITE_VERSION_NUMBER 3052000 -#define SQLITE_SOURCE_ID "2026-03-06 16:01:44 557aeb43869d3585137b17690cb3b64f7de6921774daae9e56403c3717dceab6" -#define SQLITE_SCM_BRANCH "trunk" -#define SQLITE_SCM_TAGS "release major-release version-3.52.0" -#define SQLITE_SCM_DATETIME "2026-03-06T16:01:44.367Z" +#define SQLITE_VERSION "3.51.3" +#define SQLITE_VERSION_NUMBER 3051003 +#define SQLITE_SOURCE_ID "2026-03-13 10:38:09 737ae4a34738ffa0c3ff7f9bb18df914dd1cad163f28fd6b6e114a344fe6d618" +#define SQLITE_SCM_BRANCH "branch-3.51" +#define SQLITE_SCM_TAGS "release version-3.51.3" +#define SQLITE_SCM_DATETIME "2026-03-13T10:38:09.694Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1490,7 +1490,7 @@ typedef const char *sqlite3_filename; ** greater and the function pointer is not NULL) and will fall back ** to xCurrentTime() if xCurrentTimeInt64() is unavailable. ** -** ^The xSetSystemCall(), xGetSystemCall(), and xNextSystemCall() interfaces +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces ** are not used by the SQLite core. These optional interfaces are provided ** by some VFSes to facilitate testing of the VFS code. By overriding ** system calls with functions under its control, a test program can @@ -2567,15 +2567,12 @@ struct sqlite3_mem_methods { ** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]] **
    SQLITE_DBCONFIG_STMT_SCANSTATUS
    **
    The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in -** [SQLITE_ENABLE_STMT_SCANSTATUS] builds. In this case, it sets or clears -** a flag that enables collection of run-time performance statistics -** used by [sqlite3_stmt_scanstatus_v2()] and the [nexec and ncycle] -** columns of the [bytecode virtual table]. -** For statistics to be collected, the flag must be set on -** the database handle both when the SQL statement is -** [sqlite3_prepare|prepared] and when it is [sqlite3_step|stepped]. -** The flag is set (collection of statistics is enabled) by default. -**

    This option takes two arguments: an integer and a pointer to +** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears +** a flag that enables collection of the sqlite3_stmt_scanstatus_v2() +** statistics. For statistics to be collected, the flag must be set on +** the database handle both when the SQL statement is prepared and when it +** is stepped. The flag is set (collection of statistics is enabled) +** by default.

    This option takes two arguments: an integer and a pointer to ** an integer. The first argument is 1, 0, or -1 to enable, disable, or ** leave unchanged the statement scanstatus option. If the second argument ** is not NULL, then the value of the statement scanstatus setting after @@ -2648,22 +2645,6 @@ struct sqlite3_mem_methods { ** comments are allowed in SQL text after processing the first argument. **

    ** -** [[SQLITE_DBCONFIG_FP_DIGITS]] -**
    SQLITE_DBCONFIG_FP_DIGITS
    -**
    The SQLITE_DBCONFIG_FP_DIGITS setting is a small integer that determines -** the number of significant digits that SQLite will attempt to preserve when -** converting floating point numbers (IEEE 754 "doubles") into text. The -** default value 17, as of SQLite version 3.52.0. The value was 15 in all -** prior versions.

    -** This option takes two arguments which are an integer and a pointer -** to an integer. The first argument is a small integer, between 3 and 23, or -** zero. The FP_DIGITS setting is changed to that small integer, or left -** altered if the first argument is zero or out of range. The second argument -** is a pointer to an integer. If the pointer is not NULL, then the value of -** the FP_DIGITS setting, after possibly being modified by the first -** arguments, is written into the integer to which the second argument points. -**

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

    Arguments To SQLITE_DBCONFIG Options

    @@ -2681,10 +2662,9 @@ struct sqlite3_mem_methods { ** the first argument. ** **

    While most SQLITE_DBCONFIG options use the argument format -** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME], -** [SQLITE_DBCONFIG_LOOKASIDE], and [SQLITE_DBCONFIG_FP_DIGITS] options -** are different. See the documentation of those exceptional options for -** details. +** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME] +** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the +** documentation of those exceptional options for details. */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ @@ -2709,8 +2689,7 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */ -#define SQLITE_DBCONFIG_FP_DIGITS 1023 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1023 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4192,7 +4171,6 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename); **

  • sqlite3_errmsg() **
  • sqlite3_errmsg16() **
  • sqlite3_error_offset() -**
  • sqlite3_db_handle() ** ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -4239,7 +4217,7 @@ SQLITE_API const char *sqlite3_errstr(int); SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* -** CAPI3REF: Set Error Code And Message +** CAPI3REF: Set Error Codes And Message ** METHOD: sqlite3 ** ** Set the error code of the database handle passed as the first argument @@ -4358,10 +4336,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
    SQLITE_LIMIT_EXPR_DEPTH
    **
    The maximum depth of the parse tree on any expression.
    )^ ** -** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(
    SQLITE_LIMIT_PARSER_DEPTH
    -**
    The maximum depth of the LALR(1) parser stack used to analyze -** input SQL statements.
    )^ -** ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    **
    The maximum number of terms in a compound SELECT statement.
    )^ ** @@ -4406,7 +4380,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 -#define SQLITE_LIMIT_PARSER_DEPTH 12 /* ** CAPI3REF: Prepare Flags @@ -4451,29 +4424,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** fails, the sqlite3_prepare_v3() call returns the same error indications ** with or without this flag; it just omits the call to [sqlite3_log()] that ** logs the error. -** -** [[SQLITE_PREPARE_FROM_DDL]]
    SQLITE_PREPARE_FROM_DDL
    -**
    The SQLITE_PREPARE_FROM_DDL flag causes the SQL compiler to enforce -** security constraints that would otherwise only be enforced when parsing -** the database schema. In other words, the SQLITE_PREPARE_FROM_DDL flag -** causes the SQL compiler to treat the SQL statement being prepared as if -** it had come from an attacker. When SQLITE_PREPARE_FROM_DDL is used and -** [SQLITE_DBCONFIG_TRUSTED_SCHEMA] is off, SQL functions may only be called -** if they are tagged with [SQLITE_INNOCUOUS] and virtual tables may only -** be used if they are tagged with [SQLITE_VTAB_INNOCUOUS]. Best practice -** is to use the SQLITE_PREPARE_FROM_DDL option when preparing any SQL that -** is derived from parts of the database schema. In particular, virtual -** table implementations that run SQL statements that are derived from -** arguments to their CREATE VIRTUAL TABLE statement should always use -** [sqlite3_prepare_v3()] and set the SQLITE_PREPARE_FROM_DDL flag to -** prevent bypass of the [SQLITE_DBCONFIG_TRUSTED_SCHEMA] security checks. ** */ #define SQLITE_PREPARE_PERSISTENT 0x01 #define SQLITE_PREPARE_NORMALIZE 0x02 #define SQLITE_PREPARE_NO_VTAB 0x04 #define SQLITE_PREPARE_DONT_LOG 0x10 -#define SQLITE_PREPARE_FROM_DDL 0x20 /* ** CAPI3REF: Compiling An SQL Statement @@ -4487,9 +4443,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** ** 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 -** [SQLITE_PREPARE_FROM_DDL|"prepFlags" option] that is some times -** needed for special purpose or to pass along security restrictions. +** [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 @@ -4894,8 +4849,8 @@ typedef struct sqlite3_context sqlite3_context; ** it should be a pointer to well-formed UTF16 text. ** ^If the third parameter to sqlite3_bind_text64() is not NULL, then ** it should be a pointer to a well-formed unicode string that is -** either UTF8 if the sixth parameter is SQLITE_UTF8 or SQLITE_UTF8_ZT, -** or UTF16 otherwise. +** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 +** otherwise. ** ** [[byte-order determination rules]] ^The byte-order of ** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) @@ -4941,15 +4896,10 @@ typedef struct sqlite3_context sqlite3_context; ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** -** ^The sixth argument (the E argument) -** to sqlite3_bind_text64(S,K,Z,N,D,E) must be one of -** [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE] to specify the encoding of the text in the -** third parameter, Z. The special value [SQLITE_UTF8_ZT] means that the -** string argument is both UTF-8 encoded and is zero-terminated. In other -** words, SQLITE_UTF8_ZT means that the Z array is allocated to hold at -** least N+1 bytes and that the Z[N] byte is zero. If -** the E argument to sqlite3_bind_text64(S,K,Z,N,D,E) is not one of the +** ^The sixth argument to sqlite3_bind_text64() must be one of +** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] +** to specify the encoding of the text in the third parameter. If +** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior ** is undefined. @@ -5816,51 +5766,6 @@ SQLITE_API int sqlite3_create_window_function( ** ** These constants define integer codes that represent the various ** text encodings supported by SQLite. -** -**
    -** [[SQLITE_UTF8]]
    SQLITE_UTF8
    Text is encoding as UTF-8
    -** -** [[SQLITE_UTF16LE]]
    SQLITE_UTF16LE
    Text is encoding as UTF-16 -** with each code point being expressed "little endian" - the least significant -** byte first. This is the usual encoding, for example on Windows.
    -** -** [[SQLITE_UTF16BE]]
    SQLITE_UTF16BE
    Text is encoding as UTF-16 -** with each code point being expressed "big endian" - the most significant -** byte first. This encoding is less common, but is still sometimes seen, -** specially on older systems. -** -** [[SQLITE_UTF16]]
    SQLITE_UTF16
    Text is encoding as UTF-16 -** with each code point being expressed either little endian or as big -** endian, according to the native endianness of the host computer. -** -** [[SQLITE_ANY]]
    SQLITE_ANY
    This encoding value may only be used -** to declare the preferred text for [application-defined SQL functions] -** created using [sqlite3_create_function()] and similar. If the preferred -** encoding (the 4th parameter to sqlite3_create_function() - the eTextRep -** parameter) is SQLITE_ANY, that indicates that the function does not have -** a preference regarding the text encoding of its parameters and can take -** any text encoding that the SQLite core find convenient to supply. This -** option is deprecated. Please do not use it in new applications. -** -** [[SQLITE_UTF16_ALIGNED]]
    SQLITE_UTF16_ALIGNED
    This encoding -** value may be used as the 3rd parameter (the eTextRep parameter) to -** [sqlite3_create_collation()] and similar. This encoding value means -** that the application-defined collating sequence created expects its -** input strings to be in UTF16 in native byte order, and that the start -** of the strings must be aligned to a 2-byte boundary. -** -** [[SQLITE_UTF8_ZT]]
    SQLITE_UTF8_ZT
    This option can only be -** used to specify the text encoding to strings input to [sqlite3_result_text64()] -** and [sqlite3_bind_text64()]. It means that the input string (call it "z") -** is UTF-8 encoded and that it is zero-terminated. If the length parameter -** (call it "n") is non-negative, this encoding option means that the caller -** guarantees that z array contains at least n+1 bytes and that the z[n] -** byte has a value of zero. -** This option gives the same output as SQLITE_UTF8, but can be more efficient -** by avoiding the need to make a copy of the input string, in some cases. -** However, if z is allocated to hold fewer than n+1 bytes or if the -** z[n] byte is not zero, undefined behavior may result. -**
    */ #define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ #define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ @@ -5868,7 +5773,6 @@ SQLITE_API int sqlite3_create_window_function( #define SQLITE_UTF16 4 /* Use native byte order */ #define SQLITE_ANY 5 /* Deprecated */ #define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ -#define SQLITE_UTF8_ZT 16 /* Zero-terminated UTF8 */ /* ** CAPI3REF: Function Flags @@ -6374,14 +6278,10 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi ** ** There is no limit (other than available memory) on the number of different ** client data pointers (with different names) that can be attached to a -** single database connection. However, the current implementation stores -** the content on a linked list. Insert and retrieval performance will -** be proportional to the number of entries. The design use case, and -** the use case for which the implementation is optimized, is -** that an application will store only small number of client data names, -** typically just one or two. This interface is not intended to be a -** generalized key/value store for thousands or millions of keys. It -** will work for that, but performance might be disappointing. +** single database connection. However, the implementation is optimized +** for the case of having only one or two different client data names. +** Applications and wrapper libraries are discouraged from using more than +** one client data name each. ** ** There is no way to enumerate the client data pointers ** associated with a database connection. The N parameter can be thought @@ -6489,14 +6389,10 @@ typedef void (*sqlite3_destructor_type)(void*); ** set the return value of the application-defined function to be ** a text string which is represented as UTF-8, UTF-16 native byte order, ** UTF-16 little endian, or UTF-16 big endian, respectively. -** ^The sqlite3_result_text64(C,Z,N,D,E) interface sets the return value of an +** ^The sqlite3_result_text64() interface sets the return value of an ** application-defined function to be a text string in an encoding -** specified the E parameter, which must be one -** of [SQLITE_UTF8], [SQLITE_UTF8_ZT], [SQLITE_UTF16], [SQLITE_UTF16BE], -** or [SQLITE_UTF16LE]. ^The special value [SQLITE_UTF8_ZT] means that -** the result text is both UTF-8 and zero-terminated. In other words, -** SQLITE_UTF8_ZT means that the Z array holds at least N+1 byes and that -** the Z[N] is zero. +** specified by the fifth (and last) parameter, which must be one +** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. ** ^SQLite takes the text result from the application from ** the 2nd parameter of the sqlite3_result_text* interfaces. ** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces @@ -6583,7 +6479,7 @@ SQLITE_API void sqlite3_result_int(sqlite3_context*, int); SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); SQLITE_API void sqlite3_result_null(sqlite3_context*); SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); -SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char *z, sqlite3_uint64 n, +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, void(*)(void*), unsigned char encoding); SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); @@ -7522,7 +7418,7 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The sqlite3_load_extension() interface attempts to load an ** [SQLite extension] library contained in the file zFile. If ** the file cannot be loaded directly, attempts are made to load -** with various operating-system specific filename extensions added. +** with various operating-system specific extensions added. ** So for example, if "samplelib" cannot be loaded, then names like ** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might ** be tried also. @@ -7530,10 +7426,10 @@ SQLITE_API int sqlite3_table_column_metadata( ** ^The entry point is zProc. ** ^(zProc may be 0, in which case SQLite will try to come up with an ** entry point name on its own. It first tries "sqlite3_extension_init". -** If that does not work, it tries names of the form "sqlite3_X_init" -** where X consists of the lower-case equivalent of all ASCII alphabetic -** characters or all ASCII alphanumeric characters in the filename from -** the last "/" to the first following "." and omitting any initial "lib".)^ +** If that does not work, it constructs a name "sqlite3_X_init" where +** X consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the @@ -8826,22 +8722,17 @@ SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); ** pass the returned value to [sqlite3_free()] to avoid a memory leak. ** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any ** errors were encountered during construction of the string. ^The -** [sqlite3_str_finish(X)] interface might also return a NULL pointer if the +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the ** string in [sqlite3_str] object X is zero bytes long. -** -** ^The [sqlite3_str_free(X)] interface destroys both the sqlite3_str object -** X and the string content it contains. Calling sqlite3_str_free(X) is -** the equivalent of calling [sqlite3_free](sqlite3_str_finish(X)). */ SQLITE_API char *sqlite3_str_finish(sqlite3_str*); -SQLITE_API void sqlite3_str_free(sqlite3_str*); /* ** CAPI3REF: Add Content To A Dynamic String ** METHOD: sqlite3_str ** -** These interfaces add or remove content to an sqlite3_str object -** previously obtained from [sqlite3_str_new()]. +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. ** ** ^The [sqlite3_str_appendf(X,F,...)] and ** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] @@ -8864,10 +8755,6 @@ SQLITE_API void sqlite3_str_free(sqlite3_str*); ** ^The [sqlite3_str_reset(X)] method resets the string under construction ** inside [sqlite3_str] object X back to zero bytes in length. ** -** ^The [sqlite3_str_truncate(X,N)] method changes the length of the string -** under construction to be N bytes are less. This routine is a no-op if -** N is negative or if the string is already N bytes or smaller in size. -** ** These methods do not return a result code. ^If an error occurs, that fact ** is recorded in the [sqlite3_str] object and can be recovered by a ** subsequent call to [sqlite3_str_errcode(X)]. @@ -8878,7 +8765,6 @@ SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); SQLITE_API void sqlite3_str_reset(sqlite3_str*); -SQLITE_API void sqlite3_str_truncate(sqlite3_str*,int N); /* ** CAPI3REF: Status Of A Dynamic String @@ -10712,9 +10598,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** a variable pointed to by the "pOut" parameter. ** ** The "flags" parameter must be passed a mask of flags. At present only -** one flag is defined - [SQLITE_SCANSTAT_COMPLEX]. If SQLITE_SCANSTAT_COMPLEX +** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX ** is specified, then status information is available for all elements -** of a query plan that are reported by "[EXPLAIN QUERY PLAN]" output. If +** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If ** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements ** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of ** the EXPLAIN QUERY PLAN output) are available. Invoking API @@ -10728,8 +10614,7 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value ** ** elements used to implement the statement - a non-zero value is returned and ** the variable that pOut points to is unchanged. ** -** See also: [sqlite3_stmt_scanstatus_reset()] and the -** [nexec and ncycle] columnes of the [bytecode virtual table]. +** See also: [sqlite3_stmt_scanstatus_reset()] */ SQLITE_API int sqlite3_stmt_scanstatus( sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ @@ -11271,41 +11156,19 @@ SQLITE_API int sqlite3_deserialize( /* ** CAPI3REF: Bind array values to the CARRAY table-valued function ** -** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to -** parameter that is the first argument of the [carray() table-valued function]. -** The S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. I must be the index of the -** parameter that is the first argument to the carray() table-valued function. -** P is a pointer to the array to be bound, and N is the number of elements in -** the array. The F argument is one of constants [SQLITE_CARRAY_INT32], -** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], -** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P. -** -** If the X argument is not a NULL pointer or one of the special -** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke -** the function X with argument D when it is finished using the data in P. -** The call to X(D) is a destructor for the array P. The destructor X(D) -** is invoked even if the call to sqlite3_carray_bind() fails. If the X -** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes -** that the data static and the destructor is never invoked. If the X -** parameter is the special-case value [SQLITE_TRANSIENT], then -** sqlite3_carray_bind_v2() makes its own private copy of the data prior -** to returning and never invokes the destructor X. -** -** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2() -** with a D parameter set to P. In other words, -** sqlite3_carray_bind(S,I,P,N,F,X) is same as -** sqlite3_carray_bind(S,I,P,N,F,X,P). -*/ -SQLITE_API int sqlite3_carray_bind_v2( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*), /* Destructor for aData */ - void *pDel /* Optional argument to xDel() */ -); +** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to +** one of the first argument of the [carray() table-valued function]. The +** S parameter is a pointer to the [prepared statement] that uses the carray() +** functions. I is the parameter index to be bound. P is a pointer to the +** array to be bound, and N is the number of eements in the array. The +** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], +** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to +** indicate the datatype of the array being bound. The X argument is not a +** NULL pointer, then SQLite will invoke the function X on the P parameter +** after it has finished using P, even if the call to +** sqlite3_carray_bind() fails. The special-case finalizer +** SQLITE_TRANSIENT has no effect here. +*/ SQLITE_API int sqlite3_carray_bind( sqlite3_stmt *pStmt, /* Statement to be bound */ int i, /* Parameter index */ diff --git a/deps/sqlite/sqlite3ext.h b/deps/sqlite/sqlite3ext.h index cad1a2a0016041..5258faaed313c7 100644 --- a/deps/sqlite/sqlite3ext.h +++ b/deps/sqlite/sqlite3ext.h @@ -371,11 +371,7 @@ struct sqlite3_api_routines { /* Version 3.51.0 and later */ int (*set_errmsg)(sqlite3*,int,const char*); int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int); - /* Version 3.52.0 and later */ - void (*str_truncate)(sqlite3_str*,int); - void (*str_free)(sqlite3_str*); - int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); - int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); + }; /* @@ -714,11 +710,6 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.51.0 and later */ #define sqlite3_set_errmsg sqlite3_api->set_errmsg #define sqlite3_db_status64 sqlite3_api->db_status64 -/* Version 3.52.0 and later */ -#define sqlite3_str_truncate sqlite3_api->str_truncate -#define sqlite3_str_free sqlite3_api->str_free -#define sqlite3_carray_bind sqlite3_api->carray_bind -#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) From 2000caccde4efdc885a278f5b4fe2e7e6fa87144 Mon Sep 17 00:00:00 2001 From: sangwook Date: Tue, 17 Mar 2026 16:57:07 +0900 Subject: [PATCH 034/106] util: allow color aliases in styleText MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes an issue where `util.styleText()` would throw an error for valid color aliases like 'grey' in Node.js >= 25.7.0. It now uses `ObjectGetOwnPropertyNames` instead of `ObjectKeys` to fetch both keys and aliases. Fixes: https://github.com/nodejs/node/issues/62177 PR-URL: https://github.com/nodejs/node/pull/62180 Reviewed-By: René Reviewed-By: Zeyu "Alex" Yang --- lib/util.js | 5 +++-- test/parallel/test-util-styletext.js | 33 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/util.js b/lib/util.js index 5d3c0c75a28fc5..54b7e2f9a442f7 100644 --- a/lib/util.js +++ b/lib/util.js @@ -32,6 +32,7 @@ const { ObjectDefineProperties, ObjectDefineProperty, ObjectGetOwnPropertyDescriptors, + ObjectGetOwnPropertyNames, ObjectKeys, ObjectSetPrototypeOf, ObjectValues, @@ -115,7 +116,7 @@ function getStyleCache() { if (styleCache === undefined) { styleCache = { __proto__: null }; const colors = inspect.colors; - for (const key of ObjectKeys(colors)) { + for (const key of ObjectGetOwnPropertyNames(colors)) { const codes = colors[key]; if (codes) { const openNum = codes[0]; @@ -206,7 +207,7 @@ function styleText(format, text, options) { if (key === 'none') continue; const style = cache[key]; if (style === undefined) { - validateOneOf(key, 'format', ObjectKeys(inspect.colors)); + validateOneOf(key, 'format', ObjectGetOwnPropertyNames(inspect.colors)); } openCodes += style.openSeq; closeCodes = style.closeSeq + closeCodes; diff --git a/test/parallel/test-util-styletext.js b/test/parallel/test-util-styletext.js index 4fdf419143453c..3db01bec1c3acd 100644 --- a/test/parallel/test-util-styletext.js +++ b/test/parallel/test-util-styletext.js @@ -41,6 +41,16 @@ assert.strictEqual( '\u001b[31mtest\u001b[39m', ); +assert.strictEqual( + util.styleText('gray', 'test', { validateStream: false }), + '\u001b[90mtest\u001b[39m', +); + +assert.strictEqual( + util.styleText('grey', 'test', { validateStream: false }), + '\u001b[90mtest\u001b[39m', +); + assert.strictEqual( util.styleText(['bold', 'red'], 'test', { validateStream: false }), '\u001b[1m\u001b[31mtest\u001b[39m\u001b[22m', @@ -144,6 +154,29 @@ assert.throws(() => { code: 'ERR_INVALID_ARG_TYPE', }); +// Color aliases should be accepted (e.g. 'grey' is an alias for 'gray') +// See https://github.com/nodejs/node/issues/62177 +assert.strictEqual( + util.styleText('grey', 'test', { validateStream: false }), + util.styleText('gray', 'test', { validateStream: false }), +); +assert.strictEqual( + util.styleText('bgGrey', 'test', { validateStream: false }), + util.styleText('bgGray', 'test', { validateStream: false }), +); +assert.strictEqual( + util.styleText('blackBright', 'test', { validateStream: false }), + util.styleText('gray', 'test', { validateStream: false }), +); +assert.strictEqual( + util.styleText('faint', 'test', { validateStream: false }), + util.styleText('dim', 'test', { validateStream: false }), +); +assert.strictEqual( + util.styleText(['grey', 'bold'], 'test', { validateStream: false }), + util.styleText(['gray', 'bold'], 'test', { validateStream: false }), +); + // does not throw util.styleText('red', 'text', { stream: {}, validateStream: false }); From 2ff5cb13f515b1169bbf006aaffcb2dc9708a3f1 Mon Sep 17 00:00:00 2001 From: kovan Date: Fri, 13 Mar 2026 18:15:54 +0100 Subject: [PATCH 035/106] doc,test: clarify --eval syntax for leading '-' scripts If the script passed to --eval starts with a hyphen, the CLI parser treats it as another option flag. Document the --eval=