Index: build.gradle ================================================================== --- build.gradle +++ build.gradle @@ -3,11 +3,11 @@ buildscript { repositories { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:2.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } Index: gradle.properties ================================================================== --- gradle.properties +++ gradle.properties @@ -16,6 +16,5 @@ # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true android.useDeprecatedNdk true -org.gradle.jvmargs=-Xmx1536M Index: gradle/wrapper/gradle-wrapper.properties ================================================================== --- gradle/wrapper/gradle-wrapper.properties +++ gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 19 23:03:53 AEST 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +#Wed Oct 19 18:56:36 ICT 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip Index: gradlew ================================================================== --- gradlew +++ gradlew @@ -1,37 +1,19 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" @@ -46,11 +28,10 @@ # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false -nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) @@ -57,14 +38,29 @@ darwin=true ;; MINGW* ) msys=true ;; - NONSTOP* ) - nonstop=true - ;; esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then @@ -87,11 +83,11 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi @@ -152,20 +148,13 @@ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi -# Escape application args -for s in "${@}" ; do - s=\"$s\" - APP_ARGS=$APP_ARGS" "$s -done - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- "$DEFAULT_JVM_OPTS" "$JAVA_OPTS" "$GRADLE_OPTS" "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" Index: gradlew.bat ================================================================== --- gradlew.bat +++ gradlew.bat @@ -6,18 +6,18 @@ @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 @@ -44,13 +44,14 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windows variants +@rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 @@ -57,10 +58,15 @@ :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar Index: sqlite3/build.gradle ================================================================== --- sqlite3/build.gradle +++ sqlite3/build.gradle @@ -1,29 +1,32 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" + compileSdkVersion 23 + buildToolsVersion '24.0.3' + defaultConfig { - minSdkVersion 9 // 9 for parkNanos // 13 for ParcelFileDescriptor.adoptFd; 12 //for LruCache 7 - targetSdkVersion 25 + minSdkVersion 16 + targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call + sourceSets.main { jniLibs.srcDir 'src/main/libs' } - productFlavors { - } + } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') + compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' + compile 'com.android.support:appcompat-v7:23.4.0' } DELETED sqlite3/src/main/aidl/org/sqlite/os/ICancellationSignal.aidl Index: sqlite3/src/main/aidl/org/sqlite/os/ICancellationSignal.aidl ================================================================== --- sqlite3/src/main/aidl/org/sqlite/os/ICancellationSignal.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -** Modified to support SQLite extensions by the SQLite developers: -** sqlite-dev@sqlite.org. -*/ - -package org.sqlite.os; - -/** - * @hide - */ -interface ICancellationSignal { - oneway void cancel(); -} Index: sqlite3/src/main/java/org/sqlite/database/ExtraUtils.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/ExtraUtils.java +++ sqlite3/src/main/java/org/sqlite/database/ExtraUtils.java @@ -34,11 +34,11 @@ import org.sqlite.database.sqlite.SQLiteDiskIOException; import org.sqlite.database.sqlite.SQLiteException; import org.sqlite.database.sqlite.SQLiteFullException; import org.sqlite.database.sqlite.SQLiteProgram; import org.sqlite.database.sqlite.SQLiteStatement; -import org.sqlite.os.OperationCanceledException; +import android.os.OperationCanceledException; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.text.TextUtils; import android.util.Log; DELETED sqlite3/src/main/java/org/sqlite/database/sqlite/DatabaseUtils.java Index: sqlite3/src/main/java/org/sqlite/database/sqlite/DatabaseUtils.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/DatabaseUtils.java +++ /dev/null @@ -1,1450 +0,0 @@ -package org.sqlite.database.sqlite; - -/** - * Created by pjw on 20-Apr-2017. - */ - -import android.content.ContentValues; -import android.content.Context; -import android.content.OperationApplicationException; -import android.database.AbstractWindowedCursor; -import android.database.Cursor; -import android.database.CursorWindow; -import android.database.DatabaseUtils.InsertHelper; -import android.database.SQLException; -import android.database.sqlite.SQLiteAbortException; -import android.database.sqlite.SQLiteConstraintException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabaseCorruptException; -import android.database.sqlite.SQLiteDiskIOException; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteFullException; -import android.database.sqlite.SQLiteProgram; -import android.database.sqlite.SQLiteStatement; -//import android.os.OperationCanceledException; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.text.TextUtils; -import android.util.Log; - -import org.sqlite.os.OperationCanceledException; - -import java.io.FileNotFoundException; -import java.io.PrintStream; -import java.text.Collator; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -/** - * Static utility methods for dealing with databases and {@link Cursor}s. - */ -public class DatabaseUtils { - private static final String TAG = "DatabaseUtils"; - - private static final boolean DEBUG = false; - - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_SELECT = 1; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_UPDATE = 2; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_ATTACH = 3; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_BEGIN = 4; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_COMMIT = 5; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_ABORT = 6; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_PRAGMA = 7; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_DDL = 8; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_UNPREPARED = 9; - /** One of the values returned by {@link #getSqlStatementType(String)}. */ - public static final int STATEMENT_OTHER = 99; - - /** - * Special function for writing an exception result at the header of - * a parcel, to be used when returning an exception from a transaction. - * exception will be re-thrown by the function in another process - * @param reply Parcel to write to - * @param e The Exception to be written. - * @see Parcel#writeNoException - * @see Parcel#writeException - */ - public static final void writeExceptionToParcel(Parcel reply, Exception e) { - int code = 0; - boolean logException = true; - if (e instanceof FileNotFoundException) { - code = 1; - logException = false; - } else if (e instanceof IllegalArgumentException) { - code = 2; - } else if (e instanceof UnsupportedOperationException) { - code = 3; - } else if (e instanceof SQLiteAbortException) { - code = 4; - } else if (e instanceof SQLiteConstraintException) { - code = 5; - } else if (e instanceof SQLiteDatabaseCorruptException) { - code = 6; - } else if (e instanceof SQLiteFullException) { - code = 7; - } else if (e instanceof SQLiteDiskIOException) { - code = 8; - } else if (e instanceof SQLiteException) { - code = 9; - } else if (e instanceof OperationApplicationException) { - code = 10; - } else if (e instanceof OperationCanceledException) { - code = 11; - logException = false; - } else { - reply.writeException(e); - Log.e(TAG, "Writing exception to parcel", e); - return; - } - reply.writeInt(code); - reply.writeString(e.getMessage()); - - if (logException) { - Log.e(TAG, "Writing exception to parcel", e); - } - } - - /** - * Special function for reading an exception result from the header of - * a parcel, to be used after receiving the result of a transaction. This - * will throw the exception for you if it had been written to the Parcel, - * otherwise return and let you read the normal result data from the Parcel. - * @param reply Parcel to read from - * @see Parcel#writeNoException - * @see Parcel#readException - */ -// public static final void readExceptionFromParcel(Parcel reply) { -// int code = reply.readExceptionCode(); -// if (code == 0) return; -// String msg = reply.readString(); -// android.database.DatabaseUtils.readExceptionFromParcel(reply, msg, code); -// } -// -// public static void readExceptionWithFileNotFoundExceptionFromParcel( -// Parcel reply) throws FileNotFoundException { -// int code = reply.readExceptionCode(); -// if (code == 0) return; -// String msg = reply.readString(); -// if (code == 1) { -// throw new FileNotFoundException(msg); -// } else { -// android.database.DatabaseUtils.readExceptionFromParcel(reply, msg, code); -// } -// } -// -// public static void readExceptionWithOperationApplicationExceptionFromParcel( -// Parcel reply) throws OperationApplicationException { -// int code = reply.readExceptionCode(); -// if (code == 0) return; -// String msg = reply.readString(); -// if (code == 10) { -// throw new OperationApplicationException(msg); -// } else { -// android.database.DatabaseUtils.readExceptionFromParcel(reply, msg, code); -// } -// } - - private static final void readExceptionFromParcel(Parcel reply, String msg, int code) { - switch (code) { - case 2: - throw new IllegalArgumentException(msg); - case 3: - throw new UnsupportedOperationException(msg); - case 4: - throw new SQLiteAbortException(msg); - case 5: - throw new SQLiteConstraintException(msg); - case 6: - throw new SQLiteDatabaseCorruptException(msg); - case 7: - throw new SQLiteFullException(msg); - case 8: - throw new SQLiteDiskIOException(msg); - case 9: - throw new SQLiteException(msg); - case 11: - throw new OperationCanceledException(msg); - default: - reply.readException(code, msg); - } - } - - /** - * Binds the given Object to the given SQLiteProgram using the proper - * typing. For example, bind numbers as longs/doubles, and everything else - * as a string by call toString() on it. - * - * @param prog the program to bind the object to - * @param index the 1-based index to bind at - * @param value the value to bind - */ - public static void bindObjectToProgram(SQLiteProgram prog, int index, - Object value) { - if (value == null) { - prog.bindNull(index); - } else if (value instanceof Double || value instanceof Float) { - prog.bindDouble(index, ((Number)value).doubleValue()); - } else if (value instanceof Number) { - prog.bindLong(index, ((Number)value).longValue()); - } else if (value instanceof Boolean) { - Boolean bool = (Boolean)value; - if (bool) { - prog.bindLong(index, 1); - } else { - prog.bindLong(index, 0); - } - } else if (value instanceof byte[]){ - prog.bindBlob(index, (byte[]) value); - } else { - prog.bindString(index, value.toString()); - } - } - - /** - * Returns data type of the given object's value. - *

- * Returned values are - *

- *

- * - * @param obj the object whose value type is to be returned - * @return object value type - * @hide - */ - public static int getTypeOfObject(Object obj) { - if (obj == null) { - return Cursor.FIELD_TYPE_NULL; - } else if (obj instanceof byte[]) { - return Cursor.FIELD_TYPE_BLOB; - } else if (obj instanceof Float || obj instanceof Double) { - return Cursor.FIELD_TYPE_FLOAT; - } else if (obj instanceof Long || obj instanceof Integer - || obj instanceof Short || obj instanceof Byte) { - return Cursor.FIELD_TYPE_INTEGER; - } else { - return Cursor.FIELD_TYPE_STRING; - } - } - - /** - * Fills the specified cursor window by iterating over the contents of the cursor. - * The window is filled until the cursor is exhausted or the window runs out - * of space. - * - * The original position of the cursor is left unchanged by this operation. - * - * @param cursor The cursor that contains the data to put in the window. - * @param position The start position for filling the window. - * @param window The window to fill. - * @hide - */ - public static void cursorFillWindow(final Cursor cursor, - int position, final CursorWindow window) { - if (position < 0 || position >= cursor.getCount()) { - return; - } - final int oldPos = cursor.getPosition(); - final int numColumns = cursor.getColumnCount(); - window.clear(); - window.setStartPosition(position); - window.setNumColumns(numColumns); - if (cursor.moveToPosition(position)) { - rowloop: do { - if (!window.allocRow()) { - break; - } - for (int i = 0; i < numColumns; i++) { - final int type = cursor.getType(i); - final boolean success; - switch (type) { - case Cursor.FIELD_TYPE_NULL: - success = window.putNull(position, i); - break; - - case Cursor.FIELD_TYPE_INTEGER: - success = window.putLong(cursor.getLong(i), position, i); - break; - - case Cursor.FIELD_TYPE_FLOAT: - success = window.putDouble(cursor.getDouble(i), position, i); - break; - - case Cursor.FIELD_TYPE_BLOB: { - final byte[] value = cursor.getBlob(i); - success = value != null ? window.putBlob(value, position, i) - : window.putNull(position, i); - break; - } - - default: // assume value is convertible to String - case Cursor.FIELD_TYPE_STRING: { - final String value = cursor.getString(i); - success = value != null ? window.putString(value, position, i) - : window.putNull(position, i); - break; - } - } - if (!success) { - window.freeLastRow(); - break rowloop; - } - } - position += 1; - } while (cursor.moveToNext()); - } - cursor.moveToPosition(oldPos); - } - - /** - * Appends an SQL string to the given StringBuilder, including the opening - * and closing single quotes. Any single quotes internal to sqlString will - * be escaped. - * - * This method is deprecated because we want to encourage everyone - * to use the "?" binding form. However, when implementing a - * ContentProvider, one may want to add WHERE clauses that were - * not provided by the caller. Since "?" is a positional form, - * using it in this case could break the caller because the - * indexes would be shifted to accomodate the ContentProvider's - * internal bindings. In that case, it may be necessary to - * construct a WHERE clause manually. This method is useful for - * those cases. - * - * @param sb the StringBuilder that the SQL string will be appended to - * @param sqlString the raw string to be appended, which may contain single - * quotes - */ - public static void appendEscapedSQLString(StringBuilder sb, String sqlString) { - sb.append('\''); - if (sqlString.indexOf('\'') != -1) { - int length = sqlString.length(); - for (int i = 0; i < length; i++) { - char c = sqlString.charAt(i); - if (c == '\'') { - sb.append('\''); - } - sb.append(c); - } - } else - sb.append(sqlString); - sb.append('\''); - } - - /** - * SQL-escape a string. - */ - public static String sqlEscapeString(String value) { - StringBuilder escaper = new StringBuilder(); - - android.database.DatabaseUtils.appendEscapedSQLString(escaper, value); - - return escaper.toString(); - } - - /** - * Appends an Object to an SQL string with the proper escaping, etc. - */ - public static final void appendValueToSql(StringBuilder sql, Object value) { - if (value == null) { - sql.append("NULL"); - } else if (value instanceof Boolean) { - Boolean bool = (Boolean)value; - if (bool) { - sql.append('1'); - } else { - sql.append('0'); - } - } else { - appendEscapedSQLString(sql, value.toString()); - } - } - - /** - * Concatenates two SQL WHERE clauses, handling empty or null values. - */ - public static String concatenateWhere(String a, String b) { - if (TextUtils.isEmpty(a)) { - return b; - } - if (TextUtils.isEmpty(b)) { - return a; - } - - return "(" + a + ") AND (" + b + ")"; - } - - /** - * return the collation key - * @param name - * @return the collation key - */ - public static String getCollationKey(String name) { - byte [] arr = getCollationKeyInBytes(name); - try { - return new String(arr, 0, getKeyLen(arr), "ISO8859_1"); - } catch (Exception ex) { - return ""; - } - } - - /** - * return the collation key in hex format - * @param name - * @return the collation key in hex format - */ - public static String getHexCollationKey(String name) { - byte[] arr = getCollationKeyInBytes(name); - char[] keys = encodeHex(arr); - return new String(keys, 0, getKeyLen(arr) * 2); - } - - - /** - * Used building output as Hex - */ - private static final char[] DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - - private static char[] encodeHex(byte[] input) { - int l = input.length; - char[] out = new char[l << 1]; - - // two characters form the hex value. - for (int i = 0, j = 0; i < l; i++) { - out[j++] = DIGITS[(0xF0 & input[i]) >>> 4 ]; - out[j++] = DIGITS[ 0x0F & input[i] ]; - } - - return out; - } - - private static int getKeyLen(byte[] arr) { - if (arr[arr.length - 1] != 0) { - return arr.length; - } else { - // remove zero "termination" - return arr.length-1; - } - } - - private static byte[] getCollationKeyInBytes(String name) { - if (mColl == null) { - mColl = Collator.getInstance(); - mColl.setStrength(Collator.PRIMARY); - } - return mColl.getCollationKey(name).toByteArray(); - } - - private static Collator mColl = null; - /** - * Prints the contents of a Cursor to System.out. The position is restored - * after printing. - * - * @param cursor the cursor to print - */ - public static void dumpCursor(Cursor cursor) { - dumpCursor(cursor, System.out); - } - - /** - * Prints the contents of a Cursor to a PrintSteam. The position is restored - * after printing. - * - * @param cursor the cursor to print - * @param stream the stream to print to - */ - public static void dumpCursor(Cursor cursor, PrintStream stream) { - stream.println(">>>>> Dumping cursor " + cursor); - if (cursor != null) { - int startPos = cursor.getPosition(); - - cursor.moveToPosition(-1); - while (cursor.moveToNext()) { - dumpCurrentRow(cursor, stream); - } - cursor.moveToPosition(startPos); - } - stream.println("<<<<<"); - } - - /** - * Prints the contents of a Cursor to a StringBuilder. The position - * is restored after printing. - * - * @param cursor the cursor to print - * @param sb the StringBuilder to print to - */ - public static void dumpCursor(Cursor cursor, StringBuilder sb) { - sb.append(">>>>> Dumping cursor " + cursor + "\n"); - if (cursor != null) { - int startPos = cursor.getPosition(); - - cursor.moveToPosition(-1); - while (cursor.moveToNext()) { - dumpCurrentRow(cursor, sb); - } - cursor.moveToPosition(startPos); - } - sb.append("<<<<<\n"); - } - - /** - * Prints the contents of a Cursor to a String. The position is restored - * after printing. - * - * @param cursor the cursor to print - * @return a String that contains the dumped cursor - */ - public static String dumpCursorToString(Cursor cursor) { - StringBuilder sb = new StringBuilder(); - dumpCursor(cursor, sb); - return sb.toString(); - } - - /** - * Prints the contents of a Cursor's current row to System.out. - * - * @param cursor the cursor to print from - */ - public static void dumpCurrentRow(Cursor cursor) { - dumpCurrentRow(cursor, System.out); - } - - /** - * Prints the contents of a Cursor's current row to a PrintSteam. - * - * @param cursor the cursor to print - * @param stream the stream to print to - */ - public static void dumpCurrentRow(Cursor cursor, PrintStream stream) { - String[] cols = cursor.getColumnNames(); - stream.println("" + cursor.getPosition() + " {"); - int length = cols.length; - for (int i = 0; i< length; i++) { - String value; - try { - value = cursor.getString(i); - } catch (SQLiteException e) { - // assume that if the getString threw this exception then the column is not - // representable by a string, e.g. it is a BLOB. - value = ""; - } - stream.println(" " + cols[i] + '=' + value); - } - stream.println("}"); - } - - /** - * Prints the contents of a Cursor's current row to a StringBuilder. - * - * @param cursor the cursor to print - * @param sb the StringBuilder to print to - */ - public static void dumpCurrentRow(Cursor cursor, StringBuilder sb) { - String[] cols = cursor.getColumnNames(); - sb.append("" + cursor.getPosition() + " {\n"); - int length = cols.length; - for (int i = 0; i < length; i++) { - String value; - try { - value = cursor.getString(i); - } catch (SQLiteException e) { - // assume that if the getString threw this exception then the column is not - // representable by a string, e.g. it is a BLOB. - value = ""; - } - sb.append(" " + cols[i] + '=' + value + "\n"); - } - sb.append("}\n"); - } - - /** - * Dump the contents of a Cursor's current row to a String. - * - * @param cursor the cursor to print - * @return a String that contains the dumped cursor row - */ - public static String dumpCurrentRowToString(Cursor cursor) { - StringBuilder sb = new StringBuilder(); - dumpCurrentRow(cursor, sb); - return sb.toString(); - } - - /** - * Reads a String out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The TEXT field to read - * @param values The {@link ContentValues} to put the value into, with the field as the key - */ - public static void cursorStringToContentValues(Cursor cursor, String field, - ContentValues values) { - cursorStringToContentValues(cursor, field, values, field); - } - - /** - * Reads a String out of a field in a Cursor and writes it to an InsertHelper. - * - * @param cursor The cursor to read from - * @param field The TEXT field to read - * @param inserter The InsertHelper to bind into - * @param index the index of the bind entry in the InsertHelper - */ - public static void cursorStringToInsertHelper(Cursor cursor, String field, - android.database.DatabaseUtils.InsertHelper inserter, int index) { - inserter.bind(index, cursor.getString(cursor.getColumnIndexOrThrow(field))); - } - - /** - * Reads a String out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The TEXT field to read - * @param values The {@link ContentValues} to put the value into, with the field as the key - * @param key The key to store the value with in the map - */ - public static void cursorStringToContentValues(Cursor cursor, String field, - ContentValues values, String key) { - values.put(key, cursor.getString(cursor.getColumnIndexOrThrow(field))); - } - - /** - * Reads an Integer out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The INTEGER field to read - * @param values The {@link ContentValues} to put the value into, with the field as the key - */ - public static void cursorIntToContentValues(Cursor cursor, String field, ContentValues values) { - cursorIntToContentValues(cursor, field, values, field); - } - - /** - * Reads a Integer out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The INTEGER field to read - * @param values The {@link ContentValues} to put the value into, with the field as the key - * @param key The key to store the value with in the map - */ - public static void cursorIntToContentValues(Cursor cursor, String field, ContentValues values, - String key) { - int colIndex = cursor.getColumnIndex(field); - if (!cursor.isNull(colIndex)) { - values.put(key, cursor.getInt(colIndex)); - } else { - values.put(key, (Integer) null); - } - } - - /** - * Reads a Long out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The INTEGER field to read - * @param values The {@link ContentValues} to put the value into, with the field as the key - */ - public static void cursorLongToContentValues(Cursor cursor, String field, ContentValues values) - { - cursorLongToContentValues(cursor, field, values, field); - } - - /** - * Reads a Long out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The INTEGER field to read - * @param values The {@link ContentValues} to put the value into - * @param key The key to store the value with in the map - */ - public static void cursorLongToContentValues(Cursor cursor, String field, ContentValues values, - String key) { - int colIndex = cursor.getColumnIndex(field); - if (!cursor.isNull(colIndex)) { - Long value = Long.valueOf(cursor.getLong(colIndex)); - values.put(key, value); - } else { - values.put(key, (Long) null); - } - } - - /** - * Reads a Double out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The REAL field to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorDoubleToCursorValues(Cursor cursor, String field, ContentValues values) - { - cursorDoubleToContentValues(cursor, field, values, field); - } - - /** - * Reads a Double out of a field in a Cursor and writes it to a Map. - * - * @param cursor The cursor to read from - * @param field The REAL field to read - * @param values The {@link ContentValues} to put the value into - * @param key The key to store the value with in the map - */ - public static void cursorDoubleToContentValues(Cursor cursor, String field, - ContentValues values, String key) { - int colIndex = cursor.getColumnIndex(field); - if (!cursor.isNull(colIndex)) { - values.put(key, cursor.getDouble(colIndex)); - } else { - values.put(key, (Double) null); - } - } - - /** - * Read the entire contents of a cursor row and store them in a ContentValues. - * - * @param cursor the cursor to read from. - * @param values the {@link ContentValues} to put the row into. - */ - public static void cursorRowToContentValues(Cursor cursor, ContentValues values) { - AbstractWindowedCursor awc = - (cursor instanceof AbstractWindowedCursor) ? (AbstractWindowedCursor) cursor : null; - - String[] columns = cursor.getColumnNames(); - int length = columns.length; - for (int i = 0; i < length; i++) { - if (awc != null && awc.isBlob(i)) { - values.put(columns[i], cursor.getBlob(i)); - } else { - values.put(columns[i], cursor.getString(i)); - } - } - } - - /** - * Picks a start position for {@link Cursor#fillWindow} such that the - * window will contain the requested row and a useful range of rows - * around it. - * - * When the data set is too large to fit in a cursor window, seeking the - * cursor can become a very expensive operation since we have to run the - * query again when we move outside the bounds of the current window. - * - * We try to choose a start position for the cursor window such that - * 1/3 of the window's capacity is used to hold rows before the requested - * position and 2/3 of the window's capacity is used to hold rows after the - * requested position. - * - * @param cursorPosition The row index of the row we want to get. - * @param cursorWindowCapacity The estimated number of rows that can fit in - * a cursor window, or 0 if unknown. - * @return The recommended start position, always less than or equal to - * the requested row. - * @hide - */ - public static int cursorPickFillWindowStartPosition( - int cursorPosition, int cursorWindowCapacity) { - return Math.max(cursorPosition - cursorWindowCapacity / 3, 0); - } - - /** - * Query the table for the number of rows in the table. - * @param db the database the table is in - * @param table the name of the table to query - * @return the number of rows in the table - */ - public static long queryNumEntries(SQLiteDatabase db, String table) { - return queryNumEntries(db, table, null, null); - } - - /** - * Query the table for the number of rows in the table. - * @param db the database the table is in - * @param table the name of the table to query - * @param selection A filter declaring which rows to return, - * formatted as an SQL WHERE clause (excluding the WHERE itself). - * Passing null will count all rows for the given table - * @return the number of rows in the table filtered by the selection - */ - public static long queryNumEntries(SQLiteDatabase db, String table, String selection) { - return queryNumEntries(db, table, selection, null); - } - - /** - * Query the table for the number of rows in the table. - * @param db the database the table is in - * @param table the name of the table to query - * @param selection A filter declaring which rows to return, - * formatted as an SQL WHERE clause (excluding the WHERE itself). - * Passing null will count all rows for the given table - * @param selectionArgs You may include ?s in selection, - * which will be replaced by the values from selectionArgs, - * in order that they appear in the selection. - * The values will be bound as Strings. - * @return the number of rows in the table filtered by the selection - */ - public static long queryNumEntries(SQLiteDatabase db, String table, String selection, - String[] selectionArgs) { - String s = (!TextUtils.isEmpty(selection)) ? " where " + selection : ""; - return longForQuery(db, "select count(*) from " + table + s, - selectionArgs); - } - - /** - * Query the table to check whether a table is empty or not - * @param db the database the table is in - * @param table the name of the table to query - * @return True if the table is empty - * @hide - */ - public static boolean queryIsEmpty(SQLiteDatabase db, String table) { - long isEmpty = longForQuery(db, "select exists(select 1 from " + table + ")", null); - return isEmpty == 0; - } - - /** - * Utility method to run the query on the db and return the value in the - * first column of the first row. - */ - public static long longForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - SQLiteStatement prog = db.compileStatement(query); - try { - return longForQuery(prog, selectionArgs); - } finally { - prog.close(); - } - } - - /** - * Utility method to run the pre-compiled query and return the value in the - * first column of the first row. - */ - public static long longForQuery(SQLiteStatement prog, String[] selectionArgs) { - prog.bindAllArgsAsStrings(selectionArgs); - return prog.simpleQueryForLong(); - } - - /** - * Utility method to run the query on the db and return the value in the - * first column of the first row. - */ - public static String stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs) { - SQLiteStatement prog = db.compileStatement(query); - try { - return stringForQuery(prog, selectionArgs); - } finally { - prog.close(); - } - } - - /** - * Utility method to run the pre-compiled query and return the value in the - * first column of the first row. - */ - public static String stringForQuery(SQLiteStatement prog, String[] selectionArgs) { - prog.bindAllArgsAsStrings(selectionArgs); - return prog.simpleQueryForString(); - } - - /** - * Utility method to run the query on the db and return the blob value in the - * first column of the first row. - * - * @return A read-only file descriptor for a copy of the blob value. - */ - public static ParcelFileDescriptor blobFileDescriptorForQuery(SQLiteDatabase db, - String query, String[] selectionArgs) { - SQLiteStatement prog = db.compileStatement(query); - try { - return blobFileDescriptorForQuery(prog, selectionArgs); - } finally { - prog.close(); - } - } - - /** - * Utility method to run the pre-compiled query and return the blob value in the - * first column of the first row. - * - * @return A read-only file descriptor for a copy of the blob value. - */ - public static ParcelFileDescriptor blobFileDescriptorForQuery(SQLiteStatement prog, - String[] selectionArgs) { - prog.bindAllArgsAsStrings(selectionArgs); - return prog.simpleQueryForBlobFileDescriptor(); - } - - /** - * Reads a String out of a column in a Cursor and writes it to a ContentValues. - * Adds nothing to the ContentValues if the column isn't present or if its value is null. - * - * @param cursor The cursor to read from - * @param column The column to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorStringToContentValuesIfPresent(Cursor cursor, ContentValues values, - String column) { - final int index = cursor.getColumnIndex(column); - if (index != -1 && !cursor.isNull(index)) { - values.put(column, cursor.getString(index)); - } - } - - /** - * Reads a Long out of a column in a Cursor and writes it to a ContentValues. - * Adds nothing to the ContentValues if the column isn't present or if its value is null. - * - * @param cursor The cursor to read from - * @param column The column to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorLongToContentValuesIfPresent(Cursor cursor, ContentValues values, - String column) { - final int index = cursor.getColumnIndex(column); - if (index != -1 && !cursor.isNull(index)) { - values.put(column, cursor.getLong(index)); - } - } - - /** - * Reads a Short out of a column in a Cursor and writes it to a ContentValues. - * Adds nothing to the ContentValues if the column isn't present or if its value is null. - * - * @param cursor The cursor to read from - * @param column The column to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorShortToContentValuesIfPresent(Cursor cursor, ContentValues values, - String column) { - final int index = cursor.getColumnIndex(column); - if (index != -1 && !cursor.isNull(index)) { - values.put(column, cursor.getShort(index)); - } - } - - /** - * Reads a Integer out of a column in a Cursor and writes it to a ContentValues. - * Adds nothing to the ContentValues if the column isn't present or if its value is null. - * - * @param cursor The cursor to read from - * @param column The column to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorIntToContentValuesIfPresent(Cursor cursor, ContentValues values, - String column) { - final int index = cursor.getColumnIndex(column); - if (index != -1 && !cursor.isNull(index)) { - values.put(column, cursor.getInt(index)); - } - } - - /** - * Reads a Float out of a column in a Cursor and writes it to a ContentValues. - * Adds nothing to the ContentValues if the column isn't present or if its value is null. - * - * @param cursor The cursor to read from - * @param column The column to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorFloatToContentValuesIfPresent(Cursor cursor, ContentValues values, - String column) { - final int index = cursor.getColumnIndex(column); - if (index != -1 && !cursor.isNull(index)) { - values.put(column, cursor.getFloat(index)); - } - } - - /** - * Reads a Double out of a column in a Cursor and writes it to a ContentValues. - * Adds nothing to the ContentValues if the column isn't present or if its value is null. - * - * @param cursor The cursor to read from - * @param column The column to read - * @param values The {@link ContentValues} to put the value into - */ - public static void cursorDoubleToContentValuesIfPresent(Cursor cursor, ContentValues values, - String column) { - final int index = cursor.getColumnIndex(column); - if (index != -1 && !cursor.isNull(index)) { - values.put(column, cursor.getDouble(index)); - } - } - - /** - * This class allows users to do multiple inserts into a table using - * the same statement. - *

- * This class is not thread-safe. - *

- * - * @deprecated Use {@link SQLiteStatement} instead. - */ - @Deprecated - public static class InsertHelper { - private final SQLiteDatabase mDb; - private final String mTableName; - private HashMap mColumns; - private String mInsertSQL = null; - private SQLiteStatement mInsertStatement = null; - private SQLiteStatement mReplaceStatement = null; - private SQLiteStatement mPreparedStatement = null; - - /** - * {@hide} - * - * These are the columns returned by sqlite's "PRAGMA - * table_info(...)" command that we depend on. - */ - public static final int TABLE_INFO_PRAGMA_COLUMNNAME_INDEX = 1; - - /** - * This field was accidentally exposed in earlier versions of the platform - * so we can hide it but we can't remove it. - * - * @hide - */ - public static final int TABLE_INFO_PRAGMA_DEFAULT_INDEX = 4; - - /** - * @param db the SQLiteDatabase to insert into - * @param tableName the name of the table to insert into - */ - public InsertHelper(SQLiteDatabase db, String tableName) { - mDb = db; - mTableName = tableName; - } - - private void buildSQL() throws SQLException { - StringBuilder sb = new StringBuilder(128); - sb.append("INSERT INTO "); - sb.append(mTableName); - sb.append(" ("); - - StringBuilder sbv = new StringBuilder(128); - sbv.append("VALUES ("); - - int i = 1; - Cursor cur = null; - try { - cur = mDb.rawQuery("PRAGMA table_info(" + mTableName + ")", null); - mColumns = new HashMap(cur.getCount()); - while (cur.moveToNext()) { - String columnName = cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX); - String defaultValue = cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX); - - mColumns.put(columnName, i); - sb.append("'"); - sb.append(columnName); - sb.append("'"); - - if (defaultValue == null) { - sbv.append("?"); - } else { - sbv.append("COALESCE(?, "); - sbv.append(defaultValue); - sbv.append(")"); - } - - sb.append(i == cur.getCount() ? ") " : ", "); - sbv.append(i == cur.getCount() ? ");" : ", "); - ++i; - } - } finally { - if (cur != null) cur.close(); - } - - sb.append(sbv); - - mInsertSQL = sb.toString(); - if (DEBUG) Log.v(TAG, "insert statement is " + mInsertSQL); - } - - private SQLiteStatement getStatement(boolean allowReplace) throws SQLException { - if (allowReplace) { - if (mReplaceStatement == null) { - if (mInsertSQL == null) buildSQL(); - // chop "INSERT" off the front and prepend "INSERT OR REPLACE" instead. - String replaceSQL = "INSERT OR REPLACE" + mInsertSQL.substring(6); - mReplaceStatement = mDb.compileStatement(replaceSQL); - } - return mReplaceStatement; - } else { - if (mInsertStatement == null) { - if (mInsertSQL == null) buildSQL(); - mInsertStatement = mDb.compileStatement(mInsertSQL); - } - return mInsertStatement; - } - } - - /** - * Performs an insert, adding a new row with the given values. - * - * @param values the set of values with which to populate the - * new row - * @param allowReplace if true, the statement does "INSERT OR - * REPLACE" instead of "INSERT", silently deleting any - * previously existing rows that would cause a conflict - * - * @return the row ID of the newly inserted row, or -1 if an - * error occurred - */ - private long insertInternal(ContentValues values, boolean allowReplace) { - // Start a transaction even though we don't really need one. - // This is to help maintain compatibility with applications that - // access InsertHelper from multiple threads even though they never should have. - // The original code used to lock the InsertHelper itself which was prone - // to deadlocks. Starting a transaction achieves the same mutual exclusion - // effect as grabbing a lock but without the potential for deadlocks. - mDb.beginTransactionNonExclusive(); - try { - SQLiteStatement stmt = getStatement(allowReplace); - stmt.clearBindings(); - if (DEBUG) Log.v(TAG, "--- inserting in table " + mTableName); - for (Map.Entry e: values.valueSet()) { - final String key = e.getKey(); - int i = getColumnIndex(key); - android.database.DatabaseUtils.bindObjectToProgram(stmt, i, e.getValue()); - if (DEBUG) { - Log.v(TAG, "binding " + e.getValue() + " to column " + - i + " (" + key + ")"); - } - } - long result = stmt.executeInsert(); - mDb.setTransactionSuccessful(); - return result; - } catch (SQLException e) { - Log.e(TAG, "Error inserting " + values + " into table " + mTableName, e); - return -1; - } finally { - mDb.endTransaction(); - } - } - - /** - * Returns the index of the specified column. This is index is suitagble for use - * in calls to bind(). - * @param key the column name - * @return the index of the column - */ - public int getColumnIndex(String key) { - getStatement(false); - final Integer index = mColumns.get(key); - if (index == null) { - throw new IllegalArgumentException("column '" + key + "' is invalid"); - } - return index; - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, double value) { - mPreparedStatement.bindDouble(index, value); - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, float value) { - mPreparedStatement.bindDouble(index, value); - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, long value) { - mPreparedStatement.bindLong(index, value); - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, int value) { - mPreparedStatement.bindLong(index, value); - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, boolean value) { - mPreparedStatement.bindLong(index, value ? 1 : 0); - } - - /** - * Bind null to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - */ - public void bindNull(int index) { - mPreparedStatement.bindNull(index); - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, byte[] value) { - if (value == null) { - mPreparedStatement.bindNull(index); - } else { - mPreparedStatement.bindBlob(index, value); - } - } - - /** - * Bind the value to an index. A prepareForInsert() or prepareForReplace() - * without a matching execute() must have already have been called. - * @param index the index of the slot to which to bind - * @param value the value to bind - */ - public void bind(int index, String value) { - if (value == null) { - mPreparedStatement.bindNull(index); - } else { - mPreparedStatement.bindString(index, value); - } - } - - /** - * Performs an insert, adding a new row with the given values. - * If the table contains conflicting rows, an error is - * returned. - * - * @param values the set of values with which to populate the - * new row - * - * @return the row ID of the newly inserted row, or -1 if an - * error occurred - */ - public long insert(ContentValues values) { - return insertInternal(values, false); - } - - /** - * Execute the previously prepared insert or replace using the bound values - * since the last call to prepareForInsert or prepareForReplace. - * - *

Note that calling bind() and then execute() is not thread-safe. The only thread-safe - * way to use this class is to call insert() or replace(). - * - * @return the row ID of the newly inserted row, or -1 if an - * error occurred - */ - public long execute() { - if (mPreparedStatement == null) { - throw new IllegalStateException("you must prepare this inserter before calling " - + "execute"); - } - try { - if (DEBUG) Log.v(TAG, "--- doing insert or replace in table " + mTableName); - return mPreparedStatement.executeInsert(); - } catch (SQLException e) { - Log.e(TAG, "Error executing InsertHelper with table " + mTableName, e); - return -1; - } finally { - // you can only call this once per prepare - mPreparedStatement = null; - } - } - - /** - * Prepare the InsertHelper for an insert. The pattern for this is: - *

    - *
  • prepareForInsert() - *
  • bind(index, value); - *
  • bind(index, value); - *
  • ... - *
  • bind(index, value); - *
  • execute(); - *
- */ - public void prepareForInsert() { - mPreparedStatement = getStatement(false); - mPreparedStatement.clearBindings(); - } - - /** - * Prepare the InsertHelper for a replace. The pattern for this is: - *
    - *
  • prepareForReplace() - *
  • bind(index, value); - *
  • bind(index, value); - *
  • ... - *
  • bind(index, value); - *
  • execute(); - *
- */ - public void prepareForReplace() { - mPreparedStatement = getStatement(true); - mPreparedStatement.clearBindings(); - } - - /** - * Performs an insert, adding a new row with the given values. - * If the table contains conflicting rows, they are deleted - * and replaced with the new row. - * - * @param values the set of values with which to populate the - * new row - * - * @return the row ID of the newly inserted row, or -1 if an - * error occurred - */ - public long replace(ContentValues values) { - return insertInternal(values, true); - } - - /** - * Close this object and release any resources associated with - * it. The behavior of calling insert() after - * calling this method is undefined. - */ - public void close() { - if (mInsertStatement != null) { - mInsertStatement.close(); - mInsertStatement = null; - } - if (mReplaceStatement != null) { - mReplaceStatement.close(); - mReplaceStatement = null; - } - mInsertSQL = null; - mColumns = null; - } - } - - /** - * Creates a db and populates it with the sql statements in sqlStatements. - * - * @param context the context to use to create the db - * @param dbName the name of the db to create - * @param dbVersion the version to set on the db - * @param sqlStatements the statements to use to populate the db. This should be a single string - * of the form returned by sqlite3's .dump command (statements separated by - * semicolons) - */ - static public void createDbFromSqlStatements( - Context context, String dbName, int dbVersion, String sqlStatements) { - SQLiteDatabase db = context.openOrCreateDatabase(dbName, 0, null); - // TODO: this is not quite safe since it assumes that all semicolons at the end of a line - // terminate statements. It is possible that a text field contains ;\n. We will have to fix - // this if that turns out to be a problem. - String[] statements = TextUtils.split(sqlStatements, ";\n"); - for (String statement : statements) { - if (TextUtils.isEmpty(statement)) continue; - db.execSQL(statement); - } - db.setVersion(dbVersion); - db.close(); - } - - /** - * Returns one of the following which represent the type of the given SQL statement. - *
    - *
  1. {@link #STATEMENT_SELECT}
  2. - *
  3. {@link #STATEMENT_UPDATE}
  4. - *
  5. {@link #STATEMENT_ATTACH}
  6. - *
  7. {@link #STATEMENT_BEGIN}
  8. - *
  9. {@link #STATEMENT_COMMIT}
  10. - *
  11. {@link #STATEMENT_ABORT}
  12. - *
  13. {@link #STATEMENT_OTHER}
  14. - *
- * @param sql the SQL statement whose type is returned by this method - * @return one of the values listed above - */ - public static int getSqlStatementType(String sql) { - sql = sql.trim(); - if (sql.length() < 3) { - return STATEMENT_OTHER; - } - String prefixSql = sql.substring(0, 3).toUpperCase(Locale.ROOT); - if (prefixSql.equals("SEL")) { - return STATEMENT_SELECT; - } else if (prefixSql.equals("INS") || - prefixSql.equals("UPD") || - prefixSql.equals("REP") || - prefixSql.equals("DEL")) { - return STATEMENT_UPDATE; - } else if (prefixSql.equals("ATT")) { - return STATEMENT_ATTACH; - } else if (prefixSql.equals("COM")) { - return STATEMENT_COMMIT; - } else if (prefixSql.equals("END")) { - return STATEMENT_COMMIT; - } else if (prefixSql.equals("ROL")) { - return STATEMENT_ABORT; - } else if (prefixSql.equals("BEG")) { - return STATEMENT_BEGIN; - } else if (prefixSql.equals("PRA")) { - return STATEMENT_PRAGMA; - } else if (prefixSql.equals("CRE") || prefixSql.equals("DRO") || - prefixSql.equals("ALT")) { - return STATEMENT_DDL; - } else if (prefixSql.equals("ANA") || prefixSql.equals("DET")) { - return STATEMENT_UNPREPARED; - } - return STATEMENT_OTHER; - } - - /** - * Appends one set of selection args to another. This is useful when adding a selection - * argument to a user provided set. - */ - public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) { - if (originalValues == null || originalValues.length == 0) { - return newValues; - } - String[] result = new String[originalValues.length + newValues.length ]; - System.arraycopy(originalValues, 0, result, 0, originalValues.length); - System.arraycopy(newValues, 0, result, originalValues.length, newValues.length); - return result; - } - - /** - * Returns column index of "_id" column, or -1 if not found. - * @hide - */ - public static int findRowIdColumnIndex(String[] columnNames) { - int length = columnNames.length; - for (int i = 0; i < length; i++) { - if (columnNames[i].equals("_id")) { - return i; - } - } - return -1; - } -} DELETED sqlite3/src/main/java/org/sqlite/database/sqlite/LruCache.java Index: sqlite3/src/main/java/org/sqlite/database/sqlite/LruCache.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/LruCache.java +++ /dev/null @@ -1,372 +0,0 @@ -package org.sqlite.database.sqlite; - -/** - * Created by pjw on 20-Apr-2017. - */ - -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * A cache that holds strong references to a limited number of values. Each time - * a value is accessed, it is moved to the head of a queue. When a value is - * added to a full cache, the value at the end of that queue is evicted and may - * become eligible for garbage collection. - * - *

If your cached values hold resources that need to be explicitly released, - * override {@link #entryRemoved}. - * - *

If a cache miss should be computed on demand for the corresponding keys, - * override {@link #create}. This simplifies the calling code, allowing it to - * assume a value will always be returned, even when there's a cache miss. - * - *

By default, the cache size is measured in the number of entries. Override - * {@link #sizeOf} to size the cache in different units. For example, this cache - * is limited to 4MiB of bitmaps: - *

   {@code
- *   int cacheSize = 4 * 1024 * 1024; // 4MiB
- *   LruCache bitmapCache = new LruCache(cacheSize) {
- *       protected int sizeOf(String key, Bitmap value) {
- *           return value.getByteCount();
- *       }
- *   }}
- * - *

This class is thread-safe. Perform multiple cache operations atomically by - * synchronizing on the cache:

   {@code
- *   synchronized (cache) {
- *     if (cache.get(key) == null) {
- *         cache.put(key, value);
- *     }
- *   }}
- * - *

This class does not allow null to be used as a key or value. A return - * value of null from {@link #get}, {@link #put} or {@link #remove} is - * unambiguous: the key was not in the cache. - * - *

This class appeared in Android 3.1 (Honeycomb MR1); it's available as part - * of Android's - * Support Package for earlier releases. - */ -public class LruCache { - private final LinkedHashMap map; - - /** Size of this cache in units. Not necessarily the number of elements. */ - private int size; - private int maxSize; - - private int putCount; - private int createCount; - private int evictionCount; - private int hitCount; - private int missCount; - - /** - * @param maxSize for caches that do not override {@link #sizeOf}, this is - * the maximum number of entries in the cache. For all other caches, - * this is the maximum sum of the sizes of the entries in this cache. - */ - public LruCache(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - this.maxSize = maxSize; - this.map = new LinkedHashMap(0, 0.75f, true); - } - - /** - * Sets the size of the cache. - * - * @param maxSize The new maximum size. - */ - public void resize(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - - synchronized (this) { - this.maxSize = maxSize; - } - trimToSize(maxSize); - } - - /** - * Returns the value for {@code key} if it exists in the cache or can be - * created by {@code #create}. If a value was returned, it is moved to the - * head of the queue. This returns null if a value is not cached and cannot - * be created. - */ - public final V get(K key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - V mapValue; - synchronized (this) { - mapValue = map.get(key); - if (mapValue != null) { - hitCount++; - return mapValue; - } - missCount++; - } - - /* - * Attempt to create a value. This may take a long time, and the map - * may be different when create() returns. If a conflicting value was - * added to the map while create() was working, we leave that value in - * the map and release the created value. - */ - - V createdValue = create(key); - if (createdValue == null) { - return null; - } - - synchronized (this) { - createCount++; - mapValue = map.put(key, createdValue); - - if (mapValue != null) { - // There was a conflict so undo that last put - map.put(key, mapValue); - } else { - size += safeSizeOf(key, createdValue); - } - } - - if (mapValue != null) { - entryRemoved(false, key, createdValue, mapValue); - return mapValue; - } else { - trimToSize(maxSize); - return createdValue; - } - } - - /** - * Caches {@code value} for {@code key}. The value is moved to the head of - * the queue. - * - * @return the previous value mapped by {@code key}. - */ - public final V put(K key, V value) { - if (key == null || value == null) { - throw new NullPointerException("key == null || value == null"); - } - - V previous; - synchronized (this) { - putCount++; - size += safeSizeOf(key, value); - previous = map.put(key, value); - if (previous != null) { - size -= safeSizeOf(key, previous); - } - } - - if (previous != null) { - entryRemoved(false, key, previous, value); - } - - trimToSize(maxSize); - return previous; - } - - /** - * Remove the eldest entries until the total of remaining entries is at or - * below the requested size. - * - * @param maxSize the maximum size of the cache before returning. May be -1 - * to evict even 0-sized elements. - */ - public void trimToSize(int maxSize) { - while (true) { - K key; - V value; - synchronized (this) { - if (size < 0 || (map.isEmpty() && size != 0)) { - throw new IllegalStateException(getClass().getName() - + ".sizeOf() is reporting inconsistent results!"); - } - - if (size <= maxSize) { - break; - } - - Iterator> iterator = map.entrySet().iterator(); - if (!iterator.hasNext()) - break; - - Entry toEvict = iterator.next(); - - key = toEvict.getKey(); - value = toEvict.getValue(); - map.remove(key); - size -= safeSizeOf(key, value); - evictionCount++; - } - - entryRemoved(true, key, value, null); - } - } - - /** - * Removes the entry for {@code key} if it exists. - * - * @return the previous value mapped by {@code key}. - */ - public final V remove(K key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - V previous; - synchronized (this) { - previous = map.remove(key); - if (previous != null) { - size -= safeSizeOf(key, previous); - } - } - - if (previous != null) { - entryRemoved(false, key, previous, null); - } - - return previous; - } - - /** - * Called for entries that have been evicted or removed. This method is - * invoked when a value is evicted to make space, removed by a call to - * {@link #remove}, or replaced by a call to {@link #put}. The default - * implementation does nothing. - * - *

The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - * @param evicted true if the entry is being removed to make space, false - * if the removal was caused by a {@link #put} or {@link #remove}. - * @param newValue the new value for {@code key}, if it exists. If non-null, - * this removal was caused by a {@link #put}. Otherwise it was caused by - * an eviction or a {@link #remove}. - */ - protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} - - /** - * Called after a cache miss to compute a value for the corresponding key. - * Returns the computed value or null if no value can be computed. The - * default implementation returns null. - * - *

The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - *

If a value for {@code key} exists in the cache when this method - * returns, the created value will be released with {@link #entryRemoved} - * and discarded. This can occur when multiple threads request the same key - * at the same time (causing multiple values to be created), or when one - * thread calls {@link #put} while another is creating a value for the same - * key. - */ - protected V create(K key) { - return null; - } - - private int safeSizeOf(K key, V value) { - int result = sizeOf(key, value); - if (result < 0) { - throw new IllegalStateException("Negative size: " + key + "=" + value); - } - return result; - } - - /** - * Returns the size of the entry for {@code key} and {@code value} in - * user-defined units. The default implementation returns 1 so that size - * is the number of entries and max size is the maximum number of entries. - * - *

An entry's size must not change while it is in the cache. - */ - protected int sizeOf(K key, V value) { - return 1; - } - - /** - * Clear the cache, calling {@link #entryRemoved} on each removed entry. - */ - public final void evictAll() { - trimToSize(-1); // -1 will evict 0-sized elements - } - - /** - * For caches that do not override {@link #sizeOf}, this returns the number - * of entries in the cache. For all other caches, this returns the sum of - * the sizes of the entries in this cache. - */ - public synchronized final int size() { - return size; - } - - /** - * For caches that do not override {@link #sizeOf}, this returns the maximum - * number of entries in the cache. For all other caches, this returns the - * maximum sum of the sizes of the entries in this cache. - */ - public synchronized final int maxSize() { - return maxSize; - } - - /** - * Returns the number of times {@link #get} returned a value that was - * already present in the cache. - */ - public synchronized final int hitCount() { - return hitCount; - } - - /** - * Returns the number of times {@link #get} returned null or required a new - * value to be created. - */ - public synchronized final int missCount() { - return missCount; - } - - /** - * Returns the number of times {@link #create(Object)} returned a value. - */ - public synchronized final int createCount() { - return createCount; - } - - /** - * Returns the number of times {@link #put} was called. - */ - public synchronized final int putCount() { - return putCount; - } - - /** - * Returns the number of values that have been evicted. - */ - public synchronized final int evictionCount() { - return evictionCount; - } - - /** - * Returns a copy of the current contents of the cache, ordered from least - * recently accessed to most recently accessed. - */ - public synchronized final Map snapshot() { - return new LinkedHashMap(map); - } - - @Override public synchronized final String toString() { - int accesses = hitCount + missCount; - int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; - return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", - maxSize, hitCount, missCount, hitPercent); - } -} Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnection.java @@ -19,24 +19,22 @@ */ package org.sqlite.database.sqlite; /* import dalvik.system.BlockGuard; */ +import org.sqlite.database.sqlite.CloseGuard; import android.database.Cursor; import android.database.CursorWindow; -// We use a local version of DatabaseUtils which implements methods not available in earlier APIs -//import android.database.DatabaseUtils; +import android.database.DatabaseUtils; import org.sqlite.database.ExtraUtils; import org.sqlite.database.sqlite.SQLiteDebug.DbStats; -import org.sqlite.os.CancellationSignal; -import org.sqlite.os.OperationCanceledException; +import android.os.CancellationSignal; +import android.os.OperationCanceledException; import android.os.ParcelFileDescriptor; import android.util.Log; -// We use a local copy of LruCache which does not have the 'eldest' method of the -// original, but uses an iterator to get first entry -//import android.util.LruCache; +import android.util.LruCache; import android.util.Printer; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -700,17 +698,13 @@ throwIfStatementForbidden(statement); bindArguments(statement, bindArgs); applyBlockGuardPolicy(statement); attachCancellationSignal(cancellationSignal); try { - // The Sqlite Bindings version of this code is unable to - // use shared memory (the C++ call to createAshmemRegionWithData - // always fails), so we just return null. - //int fd = nativeExecuteForBlobFileDescriptor( - // mConnectionPtr, statement.mStatementPtr); - //return fd >= 0 ? ParcelFileDescriptor.adoptFd(fd) : null; - return null; + int fd = nativeExecuteForBlobFileDescriptor( + mConnectionPtr, statement.mStatementPtr); + return fd >= 0 ? ParcelFileDescriptor.adoptFd(fd) : null; } finally { detachCancellationSignal(cancellationSignal); } } finally { releasePreparedStatement(statement); @@ -1143,14 +1137,11 @@ dbStatsList.add(getMainDbStatsUnsafe(lookaside, pageCount, pageSize)); // Get information about attached databases. // We ignore the first row in the database list because it corresponds to // the main database which we have already described. - - // original code used the newer named CursorWindows, but not available - // in API 9 etc. Was called "collectDbStats", but name is seemingly only cosmetic - CursorWindow window = new CursorWindow(true); + CursorWindow window = new CursorWindow("collectDbStats"); try { executeForCursorWindow("PRAGMA database_list;", null, window, 0, 0, false, null); for (int i = 1; i < window.getNumRows(); i++) { String name = window.getString(i, 1); String path = window.getString(i, 2); Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteConnectionPool.java @@ -21,12 +21,12 @@ package org.sqlite.database.sqlite; import org.sqlite.database.sqlite.CloseGuard; import org.sqlite.database.sqlite.SQLiteDebug.DbStats; -import org.sqlite.os.CancellationSignal; -import org.sqlite.os.OperationCanceledException; +import android.os.CancellationSignal; +import android.os.OperationCanceledException; import android.os.SystemClock; import android.util.Log; /* import android.util.PrefixPrinter; */ import android.util.Printer; Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCursor.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCursor.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteCursor.java @@ -143,18 +143,15 @@ /* ** The AbstractWindowClass contains protected methods clearOrCreateWindow() and ** closeWindow(), which are used by the android.database.sqlite.* version of this ** class. But, since they are marked with "@hide", the following replacement ** versions are required. - ** - ** Note that we ignore the name since it seems to be cosmetic only, and is not - ** available in earlier API versions. */ private void awc_clearOrCreateWindow(String name){ CursorWindow win = getWindow(); if( win==null ){ - win = new CursorWindow(true); + win = new CursorWindow(name); setWindow(win); }else{ win.clear(); } } Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabase.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabase.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDatabase.java @@ -21,19 +21,18 @@ package org.sqlite.database.sqlite; import android.content.ContentValues; import android.database.Cursor; import org.sqlite.database.DatabaseErrorHandler; -// We use a local version of DatabaseUtils which implements methods not available in earlier APIs -//import android.database.DatabaseUtils; +import android.database.DatabaseUtils; import org.sqlite.database.ExtraUtils; import org.sqlite.database.DefaultDatabaseErrorHandler; import org.sqlite.database.SQLException; import org.sqlite.database.sqlite.SQLiteDebug.DbStats; -import org.sqlite.os.CancellationSignal; +import android.os.CancellationSignal; import android.os.Looper; -import org.sqlite.os.OperationCanceledException; +import android.os.OperationCanceledException; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Printer; Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDirectCursorDriver.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDirectCursorDriver.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteDirectCursorDriver.java @@ -20,11 +20,11 @@ package org.sqlite.database.sqlite; import android.database.Cursor; import org.sqlite.database.sqlite.SQLiteDatabase.CursorFactory; -import org.sqlite.os.CancellationSignal; +import android.os.CancellationSignal; /** * A cursor driver that uses the given query directly. * * @hide Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteProgram.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteProgram.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteProgram.java @@ -18,13 +18,12 @@ ** sqlite-dev@sqlite.org. */ package org.sqlite.database.sqlite; -// We use a local version of DatabaseUtils which implements methods not available in earlier APIs -//import android.database.DatabaseUtils; -import org.sqlite.os.CancellationSignal; +import android.database.DatabaseUtils; +import android.os.CancellationSignal; import java.util.Arrays; /** * A base class for compiled SQLite programs. Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQuery.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQuery.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQuery.java @@ -19,12 +19,12 @@ */ package org.sqlite.database.sqlite; import android.database.CursorWindow; -import org.sqlite.os.CancellationSignal; -import org.sqlite.os.OperationCanceledException; +import android.os.CancellationSignal; +import android.os.OperationCanceledException; import android.util.Log; /** * Represents a query that reads the resulting rows into a {@link SQLiteQuery}. * This class is used by {@link SQLiteCursor} and isn't useful itself. Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQueryBuilder.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQueryBuilder.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteQueryBuilder.java @@ -20,12 +20,12 @@ package org.sqlite.database.sqlite; import android.database.Cursor; import android.database.DatabaseUtils; -import org.sqlite.os.CancellationSignal; -import org.sqlite.os.OperationCanceledException; +import android.os.CancellationSignal; +import android.os.OperationCanceledException; import android.provider.BaseColumns; import android.text.TextUtils; import android.util.Log; import java.util.Iterator; Index: sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteSession.java ================================================================== --- sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteSession.java +++ sqlite3/src/main/java/org/sqlite/database/sqlite/SQLiteSession.java @@ -19,14 +19,13 @@ */ package org.sqlite.database.sqlite; import android.database.CursorWindow; -// We use a local version of DatabaseUtils which implements methods not available in earlier APIs -//import android.database.DatabaseUtils; -import org.sqlite.os.CancellationSignal; -import org.sqlite.os.OperationCanceledException; +import android.database.DatabaseUtils; +import android.os.CancellationSignal; +import android.os.OperationCanceledException; import android.os.ParcelFileDescriptor; /** * Provides a single client the ability to use a database. * DELETED sqlite3/src/main/java/org/sqlite/os/CancellationSignal.java Index: sqlite3/src/main/java/org/sqlite/os/CancellationSignal.java ================================================================== --- sqlite3/src/main/java/org/sqlite/os/CancellationSignal.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -** Modified to support SQLite extensions by the SQLite developers: -** sqlite-dev@sqlite.org. -*/ - -package org.sqlite.os; - -import org.sqlite.os.ICancellationSignal; -import android.os.RemoteException; - -/** - * Provides the ability to cancel an operation in progress. - */ -public final class CancellationSignal { - private boolean mIsCanceled; - private OnCancelListener mOnCancelListener; - private ICancellationSignal mRemote; - private boolean mCancelInProgress; - - /** - * Creates a cancellation signal, initially not canceled. - */ - public CancellationSignal() { - } - - /** - * Returns true if the operation has been canceled. - * - * @return True if the operation has been canceled. - */ - public boolean isCanceled() { - synchronized (this) { - return mIsCanceled; - } - } - - /** - * Throws {@link OperationCanceledException} if the operation has been canceled. - * - * @throws OperationCanceledException if the operation has been canceled. - */ - public void throwIfCanceled() { - if (isCanceled()) { - throw new OperationCanceledException(); - } - } - - /** - * Cancels the operation and signals the cancellation listener. - * If the operation has not yet started, then it will be canceled as soon as it does. - */ - public void cancel() { - final OnCancelListener listener; - final ICancellationSignal remote; - synchronized (this) { - if (mIsCanceled) { - return; - } - mIsCanceled = true; - mCancelInProgress = true; - listener = mOnCancelListener; - remote = mRemote; - } - - try { - if (listener != null) { - listener.onCancel(); - } - if (remote != null) { - try { - remote.cancel(); - } catch (RemoteException ex) { - } - } - } finally { - synchronized (this) { - mCancelInProgress = false; - notifyAll(); - } - } - } - - /** - * Sets the cancellation listener to be called when canceled. - * - * This method is intended to be used by the recipient of a cancellation signal - * such as a database or a content provider to handle cancellation requests - * while performing a long-running operation. This method is not intended to be - * used by applications themselves. - * - * If {@link CancellationSignal#cancel} has already been called, then the provided - * listener is invoked immediately. - * - * This method is guaranteed that the listener will not be called after it - * has been removed. - * - * @param listener The cancellation listener, or null to remove the current listener. - */ - public void setOnCancelListener(OnCancelListener listener) { - synchronized (this) { - waitForCancelFinishedLocked(); - - if (mOnCancelListener == listener) { - return; - } - mOnCancelListener = listener; - if (!mIsCanceled || listener == null) { - return; - } - } - listener.onCancel(); - } - - /** - * Sets the remote transport. - * - * If {@link CancellationSignal#cancel} has already been called, then the provided - * remote transport is canceled immediately. - * - * This method is guaranteed that the remote transport will not be called after it - * has been removed. - * - * @param remote The remote transport, or null to remove. - * - * @hide - */ - public void setRemote(ICancellationSignal remote) { - synchronized (this) { - waitForCancelFinishedLocked(); - - if (mRemote == remote) { - return; - } - mRemote = remote; - if (!mIsCanceled || remote == null) { - return; - } - } - try { - remote.cancel(); - } catch (RemoteException ex) { - } - } - - private void waitForCancelFinishedLocked() { - while (mCancelInProgress) { - try { - wait(); - } catch (InterruptedException ex) { - } - } - } - - /** - * Creates a transport that can be returned back to the caller of - * a Binder function and subsequently used to dispatch a cancellation signal. - * - * @return The new cancellation signal transport. - * - * @hide - */ - public static ICancellationSignal createTransport() { - return new Transport(); - } - - /** - * Given a locally created transport, returns its associated cancellation signal. - * - * @param transport The locally created transport, or null if none. - * @return The associated cancellation signal, or null if none. - * - * @hide - */ - public static CancellationSignal fromTransport(ICancellationSignal transport) { - if (transport instanceof Transport) { - return ((Transport)transport).mCancellationSignal; - } - return null; - } - - /** - * Listens for cancellation. - */ - public interface OnCancelListener { - /** - * Called when {@link CancellationSignal#cancel} is invoked. - */ - void onCancel(); - } - - private static final class Transport extends ICancellationSignal.Stub { - final CancellationSignal mCancellationSignal = new CancellationSignal(); - - @Override - public void cancel() throws RemoteException { - mCancellationSignal.cancel(); - } - } -} DELETED sqlite3/src/main/java/org/sqlite/os/OperationCanceledException.java Index: sqlite3/src/main/java/org/sqlite/os/OperationCanceledException.java ================================================================== --- sqlite3/src/main/java/org/sqlite/os/OperationCanceledException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -** Modified to support SQLite extensions by the SQLite developers: -** sqlite-dev@sqlite.org. -*/ - -package org.sqlite.os; - - -/** - * An exception type that is thrown when an operation in progress is canceled. - * - * @see CancellationSignal - */ -public class OperationCanceledException extends RuntimeException { - public OperationCanceledException() { - this(null); - } - - public OperationCanceledException(String message) { - super(message != null ? message : "The operation has been canceled."); - } -} Index: sqlite3/src/main/jni/Application.mk ================================================================== --- sqlite3/src/main/jni/Application.mk +++ sqlite3/src/main/jni/Application.mk @@ -1,2 +1,1 @@ -APP_ABI:=all APP_STL:=stlport_static Index: sqlite3/src/main/jni/sqlite/Android.mk ================================================================== --- sqlite3/src/main/jni/sqlite/Android.mk +++ sqlite3/src/main/jni/sqlite/Android.mk @@ -3,23 +3,22 @@ include $(CLEAR_VARS) # If using SEE, uncomment the following: # LOCAL_CFLAGS += -DSQLITE_HAS_CODEC + +# Enable SQLite extensions. +LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS5 +LOCAL_CFLAGS += -DSQLITE_ENABLE_RTREE +LOCAL_CFLAGS += -DSQLITE_ENABLE_JSON1 +LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS3 + # This is important - it causes SQLite to use memory for temp files. Since # Android has no globally writable temp directory, if this is not defined the # application throws an exception when it tries to create a temp file. # LOCAL_CFLAGS += -DSQLITE_TEMP_STORE=3 -LOCAL_CFLAGS += -DSQLITE_ENABLE_JSON1 -LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS4 -LOCAL_CFLAGS += -DSQLITE_ENABLE_FTS5 -LOCAL_CFLAGS += -DSQLITE_ENABLE_RTREE=1 -LOCAL_CFLAGS += -DSQLITE_ENABLE_COLUMN_METADATA -LOCAL_CFLAGS += -DSQLITE_SOUNDEX - LOCAL_CFLAGS += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA LOCAL_CFLAGS += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL LOCAL_CFLAGS += -U__APPLE__ LOCAL_CFLAGS += -DHAVE_STRCHRNUL=0 Index: sqlite3/src/main/jni/sqlite/sqlite3.c ================================================================== --- sqlite3/src/main/jni/sqlite/sqlite3.c +++ sqlite3/src/main/jni/sqlite/sqlite3.c @@ -1,8 +1,8 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.18.0. By combining all the individual C code files into this +** version 3.15.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. @@ -202,33 +202,16 @@ # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif -/* The GCC_VERSION and MSVC_VERSION macros are used to -** conditionally include optimizations for each of these compilers. A -** value of 0 means that compiler is not being used. The -** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific -** optimizations, and hence set all compiler macros to 0 -** -** There was once also a CLANG_VERSION macro. However, we learn that the -** version numbers in clang are for "marketing" only and are inconsistent -** and unreliable. Fortunately, all versions of clang also recognize the -** gcc version numbers and have reasonable settings for gcc version numbers, -** so the GCC_VERSION macro will be set to a correct non-zero value even -** when compiling with clang. -*/ -#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) +/* What version of GCC is being used. 0 means GCC is not being used */ +#ifdef __GNUC__ # define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) #else # define GCC_VERSION 0 #endif -#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) -# define MSVC_VERSION _MSC_VER -#else -# define MSVC_VERSION 0 -#endif /* Needed for various definitions... */ #if defined(__GNUC__) && !defined(_GNU_SOURCE) # define _GNU_SOURCE #endif @@ -389,24 +372,24 @@ ** SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite ** within its configuration management system. ^The SQLITE_SOURCE_ID -** string contains the date and time of the check-in (UTC) and a SHA1 -** or SHA3-256 hash of the entire source tree. +** string contains the date and time of the check-in (UTC) and an SHA1 +** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.18.0" -#define SQLITE_VERSION_NUMBER 3018000 -#define SQLITE_SOURCE_ID "2017-03-28 18:48:43 424a0d380332858ee55bdebc4af3789f74e70a2b3ba1cf29d84b9b4bcf3e2e37" +#define SQLITE_VERSION "3.15.1" +#define SQLITE_VERSION_NUMBER 3015001 +#define SQLITE_SOURCE_ID "2016-11-04 12:08:49 1136863c76576110e710dd5d69ab6bf347c65e36" /* ** CAPI3REF: Run-Time Library Version Numbers -** KEYWORDS: sqlite3_version sqlite3_sourceid +** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to @@ -534,15 +517,11 @@ ** sqlite3_uint64 and sqlite_uint64 types can store integer values ** between 0 and +18446744073709551615 inclusive. */ #ifdef SQLITE_INT64_TYPE typedef SQLITE_INT64_TYPE sqlite_int64; -# ifdef SQLITE_UINT64_TYPE - typedef SQLITE_UINT64_TYPE sqlite_uint64; -# else - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -# endif + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; #elif defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; #else typedef long long int sqlite_int64; @@ -851,11 +830,11 @@ ** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that ** after reboot following a crash or power loss, the only bytes in a ** file that were written at the application level might have changed ** and that adjacent bytes, even bytes within the same sector are ** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN -** flag indicates that a file cannot be deleted when open. The +** flag indicate that a file cannot be deleted when open. The ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on ** read-only media and cannot be changed even by processes with ** elevated privileges. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 @@ -1001,13 +980,10 @@ **

  • [SQLITE_IOCAP_ATOMIC16K] **
  • [SQLITE_IOCAP_ATOMIC32K] **
  • [SQLITE_IOCAP_ATOMIC64K] **
  • [SQLITE_IOCAP_SAFE_APPEND] **
  • [SQLITE_IOCAP_SEQUENTIAL] -**
  • [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] -**
  • [SQLITE_IOCAP_POWERSAFE_OVERWRITE] -**
  • [SQLITE_IOCAP_IMMUTABLE] ** ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and @@ -1317,11 +1293,10 @@ #define SQLITE_FCNTL_ZIPVFS 25 #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 -#define SQLITE_FCNTL_PDB 30 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO @@ -2270,31 +2245,18 @@ ** does not make a copy of the new main schema name string, so the application ** must ensure that the argument passed into this DBCONFIG option is unchanged ** until after the database connection closes. ** ** -**
    SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
    -**
    Usually, when a database in wal mode is closed or detached from a -** database handle, SQLite checks if this will mean that there are now no -** connections at all to the database. If so, it performs a checkpoint -** operation before closing the connection. This option may be used to -** override this behaviour. The first parameter passed to this operation -** is an integer - non-zero to disable checkpoints-on-close, or zero (the -** default) to enable them. The second parameter is a pointer to an integer -** into which is written 0 or 1 to indicate whether checkpoints-on-close -** have been disabled - 0 if they are not disabled, 1 if they are. -**
    -** ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ -#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 @@ -2315,34 +2277,24 @@ ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those ** names are not also used by explicitly declared columns. ^If ** the table has a column of type [INTEGER PRIMARY KEY] then that column ** is another alias for the rowid. ** -** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of -** the most recent successful [INSERT] into a rowid table or [virtual table] -** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not -** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred -** on the database connection D, then sqlite3_last_insert_rowid(D) returns -** zero. -** -** As well as being set automatically as rows are inserted into database -** tables, the value returned by this function may be set explicitly by -** [sqlite3_set_last_insert_rowid()] -** -** Some virtual table implementations may INSERT rows into rowid tables as -** part of committing a transaction (e.g. to flush data accumulated in memory -** to disk). In this case subsequent calls to this function return the rowid -** associated with these internal INSERT operations, which leads to -** unintuitive results. Virtual table implementations that do write to rowid -** tables in this way can avoid this problem by restoring the original -** rowid value using [sqlite3_set_last_insert_rowid()] before returning -** control to the user. -** -** ^(If an [INSERT] occurs within a trigger then this routine will -** return the [rowid] of the inserted row as long as the trigger is -** running. Once the trigger program ends, the value returned -** by this routine reverts to what it was before the trigger was fired.)^ +** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the +** most recent successful [INSERT] into a rowid table or [virtual table] +** on database connection D. +** ^Inserts into [WITHOUT ROWID] tables are not recorded. +** ^If no successful [INSERT]s into rowid tables +** have ever occurred on the database connection D, +** then sqlite3_last_insert_rowid(D) returns zero. +** +** ^(If an [INSERT] occurs within a trigger or within a [virtual table] +** method, then this routine will return the [rowid] of the inserted +** row as long as the trigger or virtual table method is running. +** But once the trigger or virtual table method ends, the value returned +** by this routine reverts to what it was before the trigger or virtual +** table method began.)^ ** ** ^An [INSERT] that fails due to a constraint violation is not a ** successful [INSERT] and does not change the value returned by this ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, ** and INSERT OR ABORT make no changes to the return value of this @@ -2365,20 +2317,10 @@ ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); -/* -** CAPI3REF: Set the Last Insert Rowid value. -** METHOD: sqlite3 -** -** The sqlite3_set_last_insert_rowid(D, R) method allows the application to -** set the value returned by calling sqlite3_last_insert_rowid(D) to R -** without inserting a row into the database. -*/ -SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); - /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** ** ^This function returns the number of rows modified, inserted or @@ -3699,13 +3641,13 @@ ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    **
    The maximum number of terms in a compound SELECT statement.
    )^ ** ** [[SQLITE_LIMIT_VDBE_OP]] ^(
    SQLITE_LIMIT_VDBE_OP
    **
    The maximum number of instructions in a virtual machine program -** used to implement an SQL statement. If [sqlite3_prepare_v2()] or -** the equivalent tries to allocate space for more than this many opcodes -** in a single prepared statement, an SQLITE_NOMEM error is returned.
    )^ +** used to implement an SQL statement. This limit is not currently +** enforced, though that might be added in some future release of +** SQLite.)^ ** ** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
    SQLITE_LIMIT_FUNCTION_ARG
    **
    The maximum number of arguments on a function.
    )^ ** ** [[SQLITE_LIMIT_ATTACHED]] ^(
    SQLITE_LIMIT_ATTACHED
    @@ -3738,11 +3680,10 @@ #define SQLITE_LIMIT_ATTACHED 7 #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 - /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** METHOD: sqlite3 @@ -3913,14 +3854,10 @@ ** rather they control the timing of when other statements modify the ** database. ^The [ATTACH] and [DETACH] statements also cause ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. -** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since -** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and -** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so -** sqlite3_stmt_readonly() returns false for those commands. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset @@ -4199,16 +4136,12 @@ /* ** CAPI3REF: Number Of Columns In A Result Set ** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the -** [prepared statement]. ^If this routine returns 0, that means the -** [prepared statement] returns no data (for example an [UPDATE]). -** ^However, just because this routine returns a positive number does not -** mean that one or more rows of data will be returned. ^A SELECT statement -** will always have a positive sqlite3_column_count() but depending on the -** WHERE clause constraints and the table content, it might return no rows. +** [prepared statement]. ^This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). ** ** See also: [sqlite3_data_count()] */ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); @@ -5713,11 +5646,11 @@ ** ^(The update hook is not invoked when internal system tables are ** modified (i.e. sqlite_master and sqlite_sequence).)^ ** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. ** ** ^In the current implementation, the update hook -** is not invoked when conflicting rows are deleted because of an +** is not invoked when duplication rows are deleted because of an ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook ** invoked when rows are deleted using the [truncate optimization]. ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** @@ -6495,16 +6428,10 @@ ** ** ^Unless it returns SQLITE_MISUSE, this function sets the ** [database connection] error code and message accessible via ** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** -** A BLOB referenced by sqlite3_blob_open() may be read using the -** [sqlite3_blob_read()] interface and modified by using -** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a -** different row of the same table using the [sqlite3_blob_reopen()] -** interface. However, the column, table, or database of a [BLOB handle] -** cannot be changed after the [BLOB handle] is opened. ** ** ^(If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects ** then the BLOB handle is marked as "expired". ** This is true if any column of the row is changed, even a column @@ -6524,14 +6451,10 @@ ** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. -** -** See also: [sqlite3_blob_close()], -** [sqlite3_blob_reopen()], [sqlite3_blob_read()], -** [sqlite3_blob_bytes()], [sqlite3_blob_write()]. */ SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -6543,15 +6466,15 @@ /* ** CAPI3REF: Move a BLOB Handle to a New Row ** METHOD: sqlite3_blob ** -** ^This function is used to move an existing [BLOB handle] so that it points +** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified ** by the rowid value passed as the second argument. Only the row can be ** changed. ^The database, table and column on which the blob handle is open -** remain the same. Moving an existing [BLOB handle] to a new row is +** remain the same. Moving an existing blob handle to a new row can be ** faster than closing the existing handle and opening a new one. ** ** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - ** it must exist and there must be either a blob or text value stored in ** the nominated column.)^ ^If the new row is not present in the table, or if @@ -8476,22 +8399,22 @@ ** ^These interfaces are only available if SQLite is compiled using the ** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. ** ** ^The [sqlite3_preupdate_hook()] interface registers a callback function ** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation -** on a database table. +** on a [rowid table]. ** ^At most one preupdate hook may be registered at a time on a single ** [database connection]; each call to [sqlite3_preupdate_hook()] overrides ** the previous setting. ** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] ** with a NULL pointer as the second parameter. ** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as ** the first parameter to callbacks. ** -** ^The preupdate hook only fires for changes to real database tables; the -** preupdate hook is not invoked for changes to [virtual tables] or to -** system tables like sqlite_master or sqlite_stat1. +** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate +** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID] +** tables. ** ** ^The second parameter to the preupdate callback is a pointer to ** the [database connection] that registered the preupdate hook. ** ^The third parameter to the preupdate callback is one of the constants ** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the @@ -8501,20 +8424,16 @@ ** will be "main" for the main database or "temp" for TEMP tables or ** the name given after the AS keyword in the [ATTACH] statement for attached ** databases.)^ ** ^The fifth parameter to the preupdate callback is the name of the ** table that is being modified. -** -** For an UPDATE or DELETE operation on a [rowid table], the sixth -** parameter passed to the preupdate callback is the initial [rowid] of the -** row being modified or deleted. For an INSERT operation on a rowid table, -** or any operation on a WITHOUT ROWID table, the value of the sixth -** parameter is undefined. For an INSERT or UPDATE on a rowid table the -** seventh parameter is the final rowid value of the row being inserted -** or updated. The value of the seventh parameter passed to the callback -** function is not defined for operations on WITHOUT ROWID tables, or for -** INSERT operations on rowid tables. +** ^The sixth parameter to the preupdate callback is the initial [rowid] of the +** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is +** undefined for SQLITE_INSERT changes. +** ^The seventh parameter to the preupdate callback is the final [rowid] of +** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is +** undefined for SQLITE_DELETE changes. ** ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces ** provide additional information about a preupdate event. These routines ** may only be called from within a preupdate callback. Invoking any of @@ -8550,12 +8469,11 @@ ** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; and so forth. ** ** See also: [sqlite3_update_hook()] */ -#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) -SQLITE_API void *sqlite3_preupdate_hook( +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( sqlite3 *db, void(*xPreUpdate)( void *pCtx, /* Copy of third arg to preupdate_hook() */ sqlite3 *db, /* Database handle */ int op, /* SQLITE_UPDATE, DELETE or INSERT */ @@ -8564,15 +8482,14 @@ sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ ), void* ); -SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -SQLITE_API int sqlite3_preupdate_count(sqlite3 *); -SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); -SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); -#endif +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error @@ -8584,11 +8501,11 @@ */ SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot -** KEYWORDS: {snapshot} {sqlite3_snapshot} +** KEYWORDS: {snapshot} ** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] ** database for some specific point in history. ** @@ -8608,13 +8525,11 @@ ** The constructor for this object is [sqlite3_snapshot_get()]. The ** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer ** to an historical snapshot (if possible). The destructor for ** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ -typedef struct sqlite3_snapshot { - unsigned char hidden[48]; -} sqlite3_snapshot; +typedef struct sqlite3_snapshot sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot ** EXPERIMENTAL ** @@ -8621,36 +8536,13 @@ ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a ** new [sqlite3_snapshot] object that records the current state of ** schema S in database connection D. ^On success, the ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. -** If there is not already a read-transaction open on schema S when -** this function is called, one is opened automatically. -** -** The following must be true for this function to succeed. If any of -** the following statements are false when sqlite3_snapshot_get() is -** called, SQLITE_ERROR is returned. The final value of *P is undefined -** in this case. -** -**
      -**
    • The database handle must be in [autocommit mode]. -** -**
    • Schema S of [database connection] D must be a [WAL mode] database. -** -**
    • There must not be a write transaction open on schema S of database -** connection D. -** -**
    • One or more transactions must have been written to the current wal -** file since it was created on disk (by any connection). This means -** that a snapshot cannot be taken on a wal mode database with no wal -** file immediately after it is first opened. At least one transaction -** must be written to it first. -**
    -** -** This function may also return SQLITE_NOMEM. If it is called with the -** database handle in autocommit mode but fails for some other reason, -** whether or not a read transaction is opened on schema S is undefined. +** ^If schema S of [database connection] D is not a [WAL mode] database +** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)] +** leaves the *P value unchanged and returns an appropriate [error code]. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** @@ -8739,32 +8631,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); -/* -** CAPI3REF: Recover snapshots from a wal file -** EXPERIMENTAL -** -** If all connections disconnect from a database file but do not perform -** a checkpoint, the existing wal file is opened along with the database -** file the next time the database is opened. At this point it is only -** possible to successfully call sqlite3_snapshot_open() to open the most -** recent snapshot of the database (the one at the head of the wal file), -** even though the wal file may contain other valid snapshots for which -** clients have sqlite3_snapshot handles. -** -** This function attempts to scan the wal file associated with database zDb -** of database handle db and make all valid snapshots available to -** sqlite3_snapshot_open(). It is an error if there is already a read -** transaction open on the database, or if the database is not a wal mode -** database. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); - /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT @@ -8946,11 +8816,11 @@ ** The session object will be used to create changesets for tables in ** database zDb, where zDb is either "main", or "temp", or the name of an ** attached database. It is not an error if database zDb is not attached ** to the database when the session object is created. */ -SQLITE_API int sqlite3session_create( +int sqlite3session_create( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of db (e.g. "main") */ sqlite3_session **ppSession /* OUT: New session object */ ); @@ -8964,11 +8834,11 @@ ** ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ -SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); +void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object ** @@ -8984,11 +8854,11 @@ ** no-op, and may be used to query the current state of the session. ** ** The return value indicates the final state of the session object: 0 if ** the session is disabled, or 1 if it is enabled. */ -SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); +int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag ** ** Each change recorded by a session object is marked as either direct or @@ -9013,11 +8883,11 @@ ** indirect flag for the specified session object. ** ** The return value indicates the final state of the indirect flag: 0 if ** it is clear, or 1 if it is set. */ -SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); +int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); /* ** CAPI3REF: Attach A Table To A Session Object ** ** If argument zTab is not NULL, then it is the name of a table to attach @@ -9043,11 +8913,11 @@ ** in one or more of their PRIMARY KEY columns. ** ** SQLITE_OK is returned if the call completes without error. Or, if an error ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. */ -SQLITE_API int sqlite3session_attach( +int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zTab /* Table name */ ); /* @@ -9057,11 +8927,11 @@ ** in tables that are not attached to the Session object, the filter is called ** to determine whether changes to the table's rows should be tracked or not. ** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. */ -SQLITE_API void sqlite3session_table_filter( +void sqlite3session_table_filter( sqlite3_session *pSession, /* Session object */ int(*xFilter)( void *pCtx, /* Copy of third arg to _filter_table() */ const char *zTab /* Table name */ ), @@ -9170,11 +9040,11 @@ ** changeset, even though the delete took place while the session was disabled. ** Or, if one field of a row is updated while a session is disabled, and ** another field of the same row is updated while the session is enabled, the ** resulting changeset will contain an UPDATE change that updates both fields. */ -SQLITE_API int sqlite3session_changeset( +int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); @@ -9214,12 +9084,11 @@ ** **
  • For each row (primary key) that exists in the to-table but not in ** the from-table, a DELETE record is added to the session object. ** **
  • For each row (primary key) that exists in both tables, but features -** different non-PK values in each, an UPDATE record is added to the -** session. +** different in each, an UPDATE record is added to the session. ** ** ** To clarify, if this function is called and then a changeset constructed ** using [sqlite3session_changeset()], then after applying that changeset to ** database zFrom the contents of the two compatible tables would be @@ -9232,11 +9101,11 @@ ** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg ** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to free this buffer using ** sqlite3_free(). */ -SQLITE_API int sqlite3session_diff( +int sqlite3session_diff( sqlite3_session *pSession, const char *zFromDb, const char *zTbl, char **pzErrMsg ); @@ -9268,11 +9137,11 @@ ** Changes within a patchset are ordered in the same way as for changesets ** generated by the sqlite3session_changeset() function (i.e. all changes for ** a single table are grouped together, tables appear in the order in which ** they were attached to the session object). */ -SQLITE_API int sqlite3session_patchset( +int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ void **ppPatchset /* OUT: Buffer containing changeset */ ); @@ -9289,11 +9158,11 @@ ** an attached table is modified and then later on the original values ** are restored. However, if this function returns non-zero, then it is ** guaranteed that a call to sqlite3session_changeset() will return a ** changeset containing zero changes. */ -SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); +int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset ** ** Create an iterator used to iterate through the contents of a changeset. @@ -9324,11 +9193,11 @@ ** this function, all changes that relate to a single table are visited ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. */ -SQLITE_API int sqlite3changeset_start( +int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); @@ -9353,11 +9222,11 @@ ** ** If an error occurs, an SQLite error code is returned. Possible error ** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or ** SQLITE_NOMEM. */ -SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); +int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator ** ** The pIter argument passed to this function may either be an iterator @@ -9381,11 +9250,11 @@ ** ** If no error occurs, SQLITE_OK is returned. If an error does occur, an ** SQLite error code is returned. The values of the output variables may not ** be trusted in this case. */ -SQLITE_API int sqlite3changeset_op( +int sqlite3changeset_op( sqlite3_changeset_iter *pIter, /* Iterator object */ const char **pzTab, /* OUT: Pointer to table name */ int *pnCol, /* OUT: Number of columns in table */ int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ int *pbIndirect /* OUT: True for an 'indirect' change */ @@ -9414,11 +9283,11 @@ ** If this function is called when the iterator does not point to a valid ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, ** SQLITE_OK is returned and the output variables populated as described ** above. */ -SQLITE_API int sqlite3changeset_pk( +int sqlite3changeset_pk( sqlite3_changeset_iter *pIter, /* Iterator object */ unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ int *pnCol /* OUT: Number of entries in output array */ ); @@ -9444,11 +9313,11 @@ ** is similar to the "old.*" columns available to update or delete triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ -SQLITE_API int sqlite3changeset_old( +int sqlite3changeset_old( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ); @@ -9477,11 +9346,11 @@ ** triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ -SQLITE_API int sqlite3changeset_new( +int sqlite3changeset_new( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); @@ -9504,11 +9373,11 @@ ** and returns SQLITE_OK. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ -SQLITE_API int sqlite3changeset_conflict( +int sqlite3changeset_conflict( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); @@ -9520,11 +9389,11 @@ ** it sets the output variable to the total number of known foreign key ** violations in the destination database and returns SQLITE_OK. ** ** In all other cases this function returns SQLITE_MISUSE. */ -SQLITE_API int sqlite3changeset_fk_conflicts( +int sqlite3changeset_fk_conflicts( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int *pnOut /* OUT: Number of FK violations */ ); @@ -9553,11 +9422,11 @@ ** rc = sqlite3changeset_finalize(); ** if( rc!=SQLITE_OK ){ ** // An error has occurred ** } */ -SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); +int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Invert A Changeset ** ** This function is used to "invert" a changeset object. Applying an inverted @@ -9583,11 +9452,11 @@ ** call to this function. ** ** WARNING/TODO: This function currently assumes that the input is a valid ** changeset. If it is not, the results are undefined. */ -SQLITE_API int sqlite3changeset_invert( +int sqlite3changeset_invert( int nIn, const void *pIn, /* Input changeset */ int *pnOut, void **ppOut /* OUT: Inverse of input */ ); /* @@ -9612,11 +9481,11 @@ ** *pnOut = 0; ** } ** ** Refer to the sqlite3_changegroup documentation below for details. */ -SQLITE_API int sqlite3changeset_concat( +int sqlite3changeset_concat( int nA, /* Number of bytes in buffer pA */ void *pA, /* Pointer to buffer containing changeset A */ int nB, /* Number of bytes in buffer pB */ void *pB, /* Pointer to buffer containing changeset B */ int *pnOut, /* OUT: Number of bytes in output changeset */ @@ -9800,11 +9669,11 @@ ** considered compatible if all of the following are true: ** **
      **
    • The table has the same name as the name recorded in the ** changeset, and -**
    • The table has at least as many columns as recorded in the +**
    • The table has the same number of columns as recorded in the ** changeset, and **
    • The table has primary key columns in the same position as ** recorded in the changeset. **
    ** @@ -9845,15 +9714,11 @@ ** the changeset the row is deleted from the target database. ** ** If a row with matching primary key values is found, but one or more of ** the non-primary key fields contains a value different from the original ** row value stored in the changeset, the conflict-handler function is -** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the -** database table has more columns than are recorded in the changeset, -** only the values of those non-primary key fields are compared against -** the current database contents - any trailing database table columns -** are ignored. +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. ** ** If no row with matching primary key values is found in the database, ** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] ** passed as the second argument. ** @@ -9864,13 +9729,11 @@ ** operation is attempted because an earlier call to the conflict handler ** function returned [SQLITE_CHANGESET_REPLACE]. ** **
    INSERT Changes
    ** For each INSERT change, an attempt is made to insert the new row into -** the database. If the changeset row contains fewer fields than the -** database table, the trailing fields are populated with their default -** values. +** the database. ** ** If the attempt to insert the row fails because the database already ** contains a row with the same primary key values, the conflict handler ** function is invoked with the second argument set to ** [SQLITE_CHANGESET_CONFLICT]. @@ -9884,17 +9747,17 @@ ** **
    UPDATE Changes
    ** For each UPDATE change, this function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values -** stored in all modified non-primary key columns also match the values -** stored in the changeset the row is updated within the target database. +** stored in all non-primary key columns also match the values stored in +** the changeset the row is updated within the target database. ** ** If a row with matching primary key values is found, but one or more of -** the modified non-primary key fields contains a value different from an -** original row value stored in the changeset, the conflict-handler function -** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since +** the non-primary key fields contains a value different from an original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since ** UPDATE changes only contain values for non-primary key fields that are ** to be modified, only those fields need to match the original values to ** avoid the SQLITE_CHANGESET_DATA conflict-handler callback. ** ** If no row with matching primary key values is found in the database, @@ -9918,11 +9781,11 @@ ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. */ -SQLITE_API int sqlite3changeset_apply( +int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ @@ -10119,11 +9982,11 @@ ** ** The sessions module never invokes an xOutput callback with the third ** parameter set to a value less than or equal to zero. Other than this, ** no guarantees are made as to the size of the chunks of data returned. */ -SQLITE_API int sqlite3changeset_apply_strm( +int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ @@ -10134,35 +9997,35 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); -SQLITE_API int sqlite3changeset_concat_strm( +int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3changeset_invert_strm( +int sqlite3changeset_invert_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3changeset_start_strm( +int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); -SQLITE_API int sqlite3session_changeset_strm( +int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3session_patchset_strm( +int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3changegroup_add_strm(sqlite3_changegroup*, @@ -10867,11 +10730,11 @@ /* ** The maximum number of opcodes in a VDBE program. ** Not currently enforced. */ #ifndef SQLITE_MAX_VDBE_OP -# define SQLITE_MAX_VDBE_OP 250000000 +# define SQLITE_MAX_VDBE_OP 25000 #endif /* ** The maximum number of arguments to an SQL function. */ @@ -11065,11 +10928,10 @@ # if defined(_MSC_VER) && _MSC_VER>=1400 # if !defined(_WIN32_WCE) # include # pragma intrinsic(_byteswap_ushort) # pragma intrinsic(_byteswap_ulong) -# pragma intrinsic(_byteswap_uint64) # pragma intrinsic(_ReadWriteBarrier) # else # include # endif # endif @@ -11604,22 +11466,10 @@ #include #include #include #include -/* -** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY. -** This allows better measurements of where memcpy() is used when running -** cachegrind. But this macro version of memcpy() is very slow so it -** should not be used in production. This is a performance measurement -** hack only. -*/ -#ifdef SQLITE_INLINE_MEMCPY -# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\ - int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);} -#endif - /* ** If compiling for a processor that lacks floating point support, ** substitute integer for floating-point */ #ifdef SQLITE_OMIT_FLOATING_POINT @@ -11700,16 +11550,13 @@ /* ** The default initial allocation for the pagecache when using separate ** pagecaches for each database connection. A positive number is the ** number of pages. A negative number N translations means that a buffer ** of -1024*N bytes is allocated and used for as many pages as it will hold. -** -** The default value of "20" was choosen to minimize the run-time of the -** speedtest1 test program with options: --shrink-memory --reprepare */ #ifndef SQLITE_DEFAULT_PCACHE_INITSZ -# define SQLITE_DEFAULT_PCACHE_INITSZ 20 +# define SQLITE_DEFAULT_PCACHE_INITSZ 100 #endif /* ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. @@ -11880,39 +11727,36 @@ ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. ** ** For best performance, an attempt is made to guess at the byte-order ** using C-preprocessor macros. If that is unsuccessful, or if -** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined +** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined ** at run-time. */ -#ifndef SQLITE_BYTEORDER -# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ +#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__arm__) -# define SQLITE_BYTEORDER 1234 -# elif defined(sparc) || defined(__ppc__) -# define SQLITE_BYTEORDER 4321 -# else -# define SQLITE_BYTEORDER 0 -# endif + defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER) +# define SQLITE_BYTEORDER 1234 +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE #endif -#if SQLITE_BYTEORDER==4321 +#if (defined(sparc) || defined(__ppc__)) \ + && !defined(SQLITE_RUNTIME_BYTEORDER) +# define SQLITE_BYTEORDER 4321 # define SQLITE_BIGENDIAN 1 # define SQLITE_LITTLEENDIAN 0 # define SQLITE_UTF16NATIVE SQLITE_UTF16BE -#elif SQLITE_BYTEORDER==1234 -# define SQLITE_BIGENDIAN 0 -# define SQLITE_LITTLEENDIAN 1 -# define SQLITE_UTF16NATIVE SQLITE_UTF16LE -#else +#endif +#if !defined(SQLITE_BYTEORDER) # ifdef SQLITE_AMALGAMATION const int sqlite3one = 1; # else extern const int sqlite3one; # endif +# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ # define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) # define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) # define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) #endif @@ -12165,18 +12009,10 @@ typedef struct VtabCtx VtabCtx; typedef struct Walker Walker; typedef struct WhereInfo WhereInfo; typedef struct With With; -/* A VList object records a mapping between parameters/variables/wildcards -** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer -** variable number associated with that parameter. See the format description -** on the sqlite3VListAdd() routine for more information. A VList is really -** just an array of integers. -*/ -typedef int VList; - /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque ** pointer types (i.e. FuncDef) defined above. */ @@ -12431,14 +12267,13 @@ ); SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*); SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags); -/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */ +/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */ #define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */ #define BTREE_AUXDELETE 0x04 /* not the primary delete operation */ -#define BTREE_APPEND 0x08 /* Insert is likely an append */ /* An instance of the BtreePayload object describes the content of a single ** entry in either an index or table btree. ** ** Index btrees (used for indexes and also WITHOUT ROWID tables) contain @@ -12458,34 +12293,31 @@ */ struct BtreePayload { const void *pKey; /* Key content for indexes. NULL for tables */ sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */ const void *pData; /* Data for tables. NULL for indexes */ - struct Mem *aMem; /* First of nMem value in the unpacked pKey */ - u16 nMem; /* Number of aMem[] value. Might be zero */ int nData; /* Size of pData. 0 if none. */ int nZero; /* Extra zero data appended after pData,nData */ }; SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, - int flags, int seekResult); + int bias, int seekResult); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); -SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*); #ifndef SQLITE_OMIT_INCRBLOB -SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *); #endif SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); @@ -12494,11 +12326,10 @@ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void); #ifndef NDEBUG SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); #endif -SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*); #ifndef SQLITE_OMIT_BTREECOUNT SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); #endif @@ -12599,11 +12430,12 @@ ** as an instance of the following structure: */ struct VdbeOp { u8 opcode; /* What operation to perform */ signed char p4type; /* One of the P4_xxx constants for p4 */ - u16 p5; /* Fifth parameter is an unsigned 16-bit integer */ + u8 notUsed1; + u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ int p3; /* The third parameter */ union p4union { /* fourth parameter */ int i; /* Integer value if p4type==P4_INT32 */ @@ -12645,11 +12477,10 @@ struct SubProgram { VdbeOp *aOp; /* Array of opcodes for sub-program */ int nOp; /* Elements in aOp[] */ int nMem; /* Number of memory cells required */ int nCsr; /* Number of cursors required */ - u8 *aOnce; /* Array of OP_Once flags */ void *token; /* id that may be used to recursive triggers */ SubProgram *pNext; /* Next sub-program already visited */ }; /* @@ -12668,25 +12499,26 @@ ** Allowed values of VdbeOp.p4type */ #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ -#define P4_COLLSEQ (-3) /* P4 is a pointer to a CollSeq structure */ -#define P4_FUNCDEF (-4) /* P4 is a pointer to a FuncDef structure */ -#define P4_KEYINFO (-5) /* P4 is a pointer to a KeyInfo structure */ -#define P4_EXPR (-6) /* P4 is a pointer to an Expr tree */ -#define P4_MEM (-7) /* P4 is a pointer to a Mem* structure */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ -#define P4_VTAB (-8) /* P4 is a pointer to an sqlite3_vtab structure */ -#define P4_REAL (-9) /* P4 is a 64-bit floating point value */ -#define P4_INT64 (-10) /* P4 is a 64-bit signed integer */ -#define P4_INT32 (-11) /* P4 is a 32-bit signed integer */ -#define P4_INTARRAY (-12) /* P4 is a vector of 32-bit integers */ -#define P4_SUBPROGRAM (-13) /* P4 is a pointer to a SubProgram structure */ -#define P4_ADVANCE (-14) /* P4 is a pointer to BtreeNext() or BtreePrev() */ -#define P4_TABLE (-15) /* P4 is a pointer to a Table structure */ -#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ +#define P4_TABLE (-20) /* P4 is a pointer to a Table structure */ +#define P4_FUNCCTX (-21) /* P4 is a pointer to an sqlite3_context object */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 #define P5_ConstraintUnique 2 #define P5_ConstraintCheck 3 @@ -12780,81 +12612,81 @@ #define OP_Divide 50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ #define OP_Remainder 51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ #define OP_Concat 52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ #define OP_Last 53 #define OP_BitNot 54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ -#define OP_IfSmaller 55 -#define OP_SorterSort 56 -#define OP_Sort 57 -#define OP_Rewind 58 -#define OP_IdxLE 59 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGT 60 /* synopsis: key=r[P3@P4] */ -#define OP_IdxLT 61 /* synopsis: key=r[P3@P4] */ -#define OP_IdxGE 62 /* synopsis: key=r[P3@P4] */ -#define OP_RowSetRead 63 /* synopsis: r[P3]=rowset(P1) */ -#define OP_RowSetTest 64 /* synopsis: if r[P3] in rowset(P1) goto P2 */ -#define OP_Program 65 -#define OP_FkIfZero 66 /* synopsis: if fkctr[P1]==0 goto P2 */ -#define OP_IfPos 67 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ -#define OP_IfNotZero 68 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ -#define OP_DecrJumpZero 69 /* synopsis: if (--r[P1])==0 goto P2 */ -#define OP_IncrVacuum 70 -#define OP_VNext 71 -#define OP_Init 72 /* synopsis: Start at P2 */ -#define OP_Return 73 -#define OP_EndCoroutine 74 -#define OP_HaltIfNull 75 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 76 -#define OP_Integer 77 /* synopsis: r[P2]=P1 */ -#define OP_Int64 78 /* synopsis: r[P2]=P4 */ -#define OP_String 79 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 80 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 81 /* synopsis: r[P1]=NULL */ -#define OP_Blob 82 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 83 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 84 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 85 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 86 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 87 /* synopsis: r[P2]=r[P1] */ -#define OP_ResultRow 88 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 89 -#define OP_Function0 90 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_Function 91 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_AddImm 92 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_RealAffinity 93 -#define OP_Cast 94 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 95 -#define OP_Compare 96 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_SorterSort 55 +#define OP_Sort 56 +#define OP_Rewind 57 +#define OP_IdxLE 58 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGT 59 /* synopsis: key=r[P3@P4] */ +#define OP_IdxLT 60 /* synopsis: key=r[P3@P4] */ +#define OP_IdxGE 61 /* synopsis: key=r[P3@P4] */ +#define OP_RowSetRead 62 /* synopsis: r[P3]=rowset(P1) */ +#define OP_RowSetTest 63 /* synopsis: if r[P3] in rowset(P1) goto P2 */ +#define OP_Program 64 +#define OP_FkIfZero 65 /* synopsis: if fkctr[P1]==0 goto P2 */ +#define OP_IfPos 66 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */ +#define OP_IfNotZero 67 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */ +#define OP_DecrJumpZero 68 /* synopsis: if (--r[P1])==0 goto P2 */ +#define OP_IncrVacuum 69 +#define OP_VNext 70 +#define OP_Init 71 /* synopsis: Start at P2 */ +#define OP_Return 72 +#define OP_EndCoroutine 73 +#define OP_HaltIfNull 74 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 75 +#define OP_Integer 76 /* synopsis: r[P2]=P1 */ +#define OP_Int64 77 /* synopsis: r[P2]=P4 */ +#define OP_String 78 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_Null 79 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 80 /* synopsis: r[P1]=NULL */ +#define OP_Blob 81 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 82 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 83 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 84 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 85 /* synopsis: r[P2]=r[P1] */ +#define OP_IntCopy 86 /* synopsis: r[P2]=r[P1] */ +#define OP_ResultRow 87 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 88 +#define OP_Function0 89 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Function 90 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_AddImm 91 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_RealAffinity 92 +#define OP_Cast 93 /* synopsis: affinity(r[P1]) */ +#define OP_Permutation 94 +#define OP_Compare 95 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_Column 96 /* synopsis: r[P3]=PX */ #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_Column 98 /* synopsis: r[P3]=PX */ -#define OP_Affinity 99 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 100 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 101 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 102 -#define OP_SetCookie 103 -#define OP_ReopenIdx 104 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 105 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 106 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 109 -#define OP_SequenceTest 110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 111 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 112 -#define OP_ColumnsUsed 113 -#define OP_Sequence 114 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 115 /* synopsis: r[P2]=rowid */ -#define OP_Insert 116 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_InsertInt 117 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_Delete 118 -#define OP_ResetCount 119 -#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 121 /* synopsis: r[P2]=data */ +#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 100 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 101 +#define OP_SetCookie 102 +#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenAutoindex 106 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 107 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 108 +#define OP_SequenceTest 109 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 110 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 111 +#define OP_ColumnsUsed 112 +#define OP_Sequence 113 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 114 /* synopsis: r[P2]=rowid */ +#define OP_Insert 115 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_InsertInt 116 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 117 +#define OP_ResetCount 118 +#define OP_SorterCompare 119 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 120 /* synopsis: r[P2]=data */ +#define OP_RowKey 121 /* synopsis: r[P2]=key */ #define OP_RowData 122 /* synopsis: r[P2]=data */ #define OP_Rowid 123 /* synopsis: r[P2]=rowid */ #define OP_NullRow 124 -#define OP_SorterInsert 125 /* synopsis: key=r[P2] */ +#define OP_SorterInsert 125 #define OP_IdxInsert 126 /* synopsis: key=r[P2] */ #define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */ #define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */ #define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */ #define OP_Destroy 130 @@ -12861,38 +12693,37 @@ #define OP_Clear 131 #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ #define OP_ResetSorter 133 #define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */ #define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */ -#define OP_SqlExec 136 -#define OP_ParseSchema 137 -#define OP_LoadAnalysis 138 -#define OP_DropTable 139 -#define OP_DropIndex 140 -#define OP_DropTrigger 141 -#define OP_IntegrityCk 142 -#define OP_RowSetAdd 143 /* synopsis: rowset(P1)=r[P2] */ -#define OP_Param 144 -#define OP_FkCounter 145 /* synopsis: fkctr[P1]+=P2 */ -#define OP_MemMax 146 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_OffsetLimit 147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggStep0 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggFinal 150 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 151 -#define OP_TableLock 152 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 153 -#define OP_VCreate 154 -#define OP_VDestroy 155 -#define OP_VOpen 156 -#define OP_VColumn 157 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 158 -#define OP_Pagecount 159 -#define OP_MaxPgcnt 160 -#define OP_CursorHint 161 -#define OP_Noop 162 -#define OP_Explain 163 +#define OP_ParseSchema 136 +#define OP_LoadAnalysis 137 +#define OP_DropTable 138 +#define OP_DropIndex 139 +#define OP_DropTrigger 140 +#define OP_IntegrityCk 141 +#define OP_RowSetAdd 142 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 143 +#define OP_FkCounter 144 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 145 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 146 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggStep0 147 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggFinal 149 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 150 +#define OP_TableLock 151 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 152 +#define OP_VCreate 153 +#define OP_VDestroy 154 +#define OP_VOpen 155 +#define OP_VColumn 156 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 157 +#define OP_Pagecount 158 +#define OP_MaxPgcnt 159 +#define OP_CursorHint 160 +#define OP_Noop 161 +#define OP_Explain 162 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c ** are encoded into bitvectors as follows: */ @@ -12908,32 +12739,32 @@ /* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\ /* 24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\ /* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\ /* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\ -/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23,\ -/* 64 */ 0x0b, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01,\ -/* 72 */ 0x01, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\ -/* 80 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\ -/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\ -/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ +/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b,\ +/* 64 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01,\ +/* 72 */ 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10,\ +/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,\ +/* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ +/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\ /* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\ -/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ -/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ -/* 160 */ 0x10, 0x00, 0x00, 0x00,} +/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\ +/* 144 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ +/* 160 */ 0x00, 0x00, 0x00,} /* The sqlite3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum ** JUMP opcode the better, so the mkopcodeh.tcl script that ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ -#define SQLITE_MX_JUMP_OPCODE 72 /* Maximum JUMP opcode */ +#define SQLITE_MX_JUMP_OPCODE 71 /* Maximum JUMP opcode */ /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ /* @@ -12952,27 +12783,24 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int); SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int); #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N); -SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); #else # define sqlite3VdbeVerifyNoMallocRequired(A,B) -# define sqlite3VdbeVerifyNoResultRow(A) #endif SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); -SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5); +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr); SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); -SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type); SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*); SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); @@ -13004,11 +12832,11 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); -SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*); +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); #ifndef SQLITE_OMIT_TRIGGER @@ -13209,11 +13037,11 @@ int, int, int, void(*)(DbPage*) ); -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); @@ -13260,25 +13088,22 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); #ifndef SQLITE_OMIT_WAL -SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); -# ifdef SQLITE_DIRECT_OVERFLOW_READ -SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno); -# endif +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager); # ifdef SQLITE_ENABLE_SNAPSHOT SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager); # endif #else -# define sqlite3PagerUseWal(x,y) 0 +# define sqlite3PagerUseWal(x) 0 #endif #ifdef SQLITE_ENABLE_ZIPVFS SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); #endif @@ -13893,11 +13718,11 @@ ** The "PRAGMA synchronous" statement also uses the zero-based numbers. ** In other words, the zero-based numbers are used for all external interfaces ** and the one-based values are used internally. */ #ifndef SQLITE_DEFAULT_SYNCHRONOUS -# define SQLITE_DEFAULT_SYNCHRONOUS 2 +# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1) #endif #ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS # define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS #endif @@ -14098,12 +13923,10 @@ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ u8 mTrace; /* zero or more SQLITE_TRACE flags */ - u8 skipBtreeMutex; /* True if no shared-cache backends */ - u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ @@ -14247,11 +14070,10 @@ #define SQLITE_QueryOnly 0x04000000 /* Disable database changes */ #define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */ #define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */ #define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */ #define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */ -#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to @@ -14273,12 +14095,17 @@ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ +#ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) +#else +#define OptimizationDisabled(db, mask) 0 +#define OptimizationEnabled(db, mask) 1 +#endif /* ** Return true if it OK to factor constant expressions into the initialization ** code. The argument is a Parse object for the code generator. */ @@ -14365,11 +14192,10 @@ #define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */ #define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ -#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** @@ -14614,19 +14440,19 @@ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ ExprList *pCheck; /* All CHECK constraints */ /* ... also used as column name list in a VIEW */ int tnum; /* Root BTree page for this table */ - u32 nTabRef; /* Number of pointers to this Table */ - u32 tabFlags; /* Mask of TF_* values */ i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ i16 nCol; /* Number of columns in this table */ + u16 nRef; /* Number of pointers to this Table */ LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ #ifdef SQLITE_ENABLE_COSTMULT LogEst costMult; /* Cost multiplier for using this table */ #endif + u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -14646,29 +14472,27 @@ ** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING ** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, ** the TF_OOOHidden attribute would apply in this case. Such tables require ** special handling during INSERT processing. */ -#define TF_Readonly 0x0001 /* Read-only system table */ -#define TF_Ephemeral 0x0002 /* An ephemeral table */ -#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */ -#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */ -#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */ -#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */ -#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */ -#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */ -#define TF_StatsUsed 0x0100 /* Query planner decisions affected by - ** Index.aiRowLogEst[] values */ -#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ +#define TF_Readonly 0x01 /* Read-only system table */ +#define TF_Ephemeral 0x02 /* An ephemeral table */ +#define TF_HasPrimaryKey 0x04 /* Table has a primary key */ +#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ +#define TF_Virtual 0x10 /* Is a virtual table */ +#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */ +#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */ +#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */ + /* ** Test to see whether or not a table is a virtual table. This is ** done as a macro so that it will be optimized out when virtual ** table support is omitted from the build. */ #ifndef SQLITE_OMIT_VIRTUALTABLE -# define IsVirtual(X) ((X)->nModuleArg) +# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) #else # define IsVirtual(X) 0 #endif /* @@ -14899,11 +14723,10 @@ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ unsigned isResized:1; /* True if resizeIndexObject() has been called */ unsigned isCovering:1; /* True if this is a covering index */ unsigned noSkipScan:1; /* Do not try to use skip-scan if true */ - unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ @@ -15210,11 +15033,11 @@ ** form is used for name resolution with nested FROM clauses. */ struct ExprList { int nExpr; /* Number of expressions on the list */ struct ExprList_item { /* For each expression in the list */ - Expr *pExpr; /* The parse tree for this expression */ + Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ u8 sortOrder; /* 1 for DESC or 0 for ASC */ unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ @@ -15375,11 +15198,11 @@ #define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */ #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */ #define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */ #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */ -#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */ + /* 0x1000 not currently used */ /* 0x2000 not currently used */ #define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */ /* 0x8000 not currently used */ /* Allowed return values from sqlite3WhereIsDistinct() @@ -15758,20 +15581,21 @@ int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ int aTempReg[8]; /* Holding area for temporary registers */ Token sNameToken; /* Token with unqualified schema object name */ + Token sLastToken; /* The last token parsed */ /************************************************************************ ** Above is constant between recursions. Below is reset before and after ** each recursion. The boundary between these two regions is determined - ** using offsetof(Parse,sLastToken) so the sLastToken field must be the - ** first field in the recursive region. + ** using offsetof(Parse,nVar) so the nVar field must be the first field + ** in the recursive region. ************************************************************************/ - Token sLastToken; /* The last token parsed */ ynVar nVar; /* Number of '?' variables seen in the SQL so far */ + int nzVar; /* Number of available slots in azVar[] */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ int nVtabLock; /* Number of virtual tables to lock */ @@ -15779,11 +15603,11 @@ int nHeight; /* Expression tree height of current sub-select */ #ifndef SQLITE_OMIT_EXPLAIN int iSelectId; /* ID of current select for EXPLAIN output */ int iNextSelectId; /* Next available select ID for EXPLAIN output */ #endif - VList *pVList; /* Mapping between variable names and numbers */ + char **azVar; /* Pointers to names of parameters */ Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ @@ -15799,11 +15623,11 @@ /* ** Sizes and pointers of various parts of the Parse object. */ #define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/ -#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ +#define PARSE_RECURSE_SZ offsetof(Parse,nVar) /* Recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ /* ** Return true if currently inside an sqlite3_declare_vtab() call. @@ -15836,23 +15660,25 @@ ** OPFLAG_AUXDELETE == BTREE_AUXDELETE */ #define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */ /* Also used in P2 (not P5) of OP_Delete */ #define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */ -#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */ +#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */ #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK #define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */ +#endif #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ #define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */ #define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ -#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */ +#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */ #define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. @@ -16045,11 +15871,11 @@ ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. */ void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */ void *pVdbeBranchArg; /* 1st argument */ #endif -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ int iOnceResetThreshold; /* When to reset OP_Once counters */ }; @@ -16249,11 +16075,11 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int); SQLITE_PRIVATE void sqlite3ScratchFree(void*); SQLITE_PRIVATE void *sqlite3PageMalloc(int); SQLITE_PRIVATE void sqlite3PageFree(void*); SQLITE_PRIVATE void sqlite3MemSetDefault(void); -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); #endif SQLITE_PRIVATE int sqlite3HeapNearlyFull(void); /* @@ -16360,11 +16186,11 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int); #endif SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); -SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); +SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*); SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); @@ -16376,13 +16202,10 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); -#ifndef SQLITE_OMIT_VIRTUALTABLE -SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); -#endif SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); @@ -16407,11 +16230,11 @@ SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); -#ifdef SQLITE_UNTESTABLE +#ifdef SQLITE_OMIT_BUILTIN_TEST # define sqlite3FaultSim(X) SQLITE_OK #else SQLITE_PRIVATE int sqlite3FaultSim(int); #endif @@ -16420,11 +16243,11 @@ SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec*, u32); SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*); SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*); -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); #endif SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*); @@ -16509,19 +16332,18 @@ SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*); SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeAtInit(Parse*, Expr*, int); +SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8); #define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ #define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ #define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */ -#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); #define LOCATE_VIEW 0x01 @@ -16533,19 +16355,18 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*); SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); #endif SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); @@ -16572,15 +16393,10 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*,int*); -#ifdef SQLITE_ENABLE_NULL_TRIM -SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*); -#else -# define sqlite3SetMakeRecordP5(A,B) -#endif SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int); SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*); SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int); SQLITE_PRIVATE void sqlite3MultiWrite(Parse*); SQLITE_PRIVATE void sqlite3MayAbort(Parse*); @@ -16683,13 +16499,10 @@ #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \ defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); #endif -SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); -SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); -SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c ** file. @@ -16855,14 +16668,12 @@ #endif /* ** The interface to the LEMON-generated parser */ -#ifndef SQLITE_AMALGAMATION -SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); -SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); -#endif +SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64)); +SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); #ifdef YYTRACKMAXSTACKDEPTH SQLITE_PRIVATE int sqlite3ParserStackPeak(void*); #endif @@ -16904,17 +16715,10 @@ SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *); SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*); SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int); SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); -SQLITE_PRIVATE Module *sqlite3VtabCreateModule( - sqlite3*, - const char*, - const sqlite3_module*, - void*, - void(*)(void*) - ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*); SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); @@ -16968,11 +16772,10 @@ #define sqlite3FkActions(a,b,c,d,e,f) #define sqlite3FkCheck(a,b,c,d,e,f) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 - #define sqlite3FkReferences(a) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**); #else @@ -16987,14 +16790,14 @@ #define SQLITE_FAULTINJECTOR_MALLOC 0 #define SQLITE_FAULTINJECTOR_COUNT 1 /* ** The interface to the code in fault.c used for identifying "benign" -** malloc failures. This is only present if SQLITE_UNTESTABLE +** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST ** is not defined. */ -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void); SQLITE_PRIVATE void sqlite3EndBenignMalloc(void); #else #define sqlite3BeginBenignMalloc() #define sqlite3EndBenignMalloc() @@ -17121,11 +16924,10 @@ SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr); SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr); SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int); SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int); -SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*); #endif /* SQLITEINT_H */ /************** End of sqliteInt.h *******************************************/ /************** Begin file global.c ******************************************/ @@ -17297,23 +17099,10 @@ ** setting.) */ #ifndef SQLITE_STMTJRNL_SPILL # define SQLITE_STMTJRNL_SPILL (64*1024) #endif - -/* -** The default lookaside-configuration, the format "SZ,N". SZ is the -** number of bytes in each lookaside slot (should be a multiple of 8) -** and N is the number of slots. The lookaside-configuration can be -** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE) -** or at run-time for an individual database connection using -** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE); -*/ -#ifndef SQLITE_DEFAULT_LOOKASIDE -# define SQLITE_DEFAULT_LOOKASIDE 1200,100 -#endif - /* ** The following singleton contains the global configuration for ** the SQLite library. */ @@ -17323,11 +17112,12 @@ SQLITE_THREADSAFE==1, /* bFullMutex */ SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ - SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ + 128, /* szLookaside */ + 500, /* nLookaside */ SQLITE_STMTJRNL_SPILL, /* nStmtSpill */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ (void*)0, /* pHeap */ @@ -17360,11 +17150,11 @@ #endif #ifdef SQLITE_VDBE_COVERAGE 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ 0x7ffffffe /* iOnceResetThreshold */ }; @@ -17480,28 +17270,19 @@ "COMPILER=gcc-" __VERSION__, #endif #if SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG "DEBUG", #endif #if SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), #endif -#if SQLITE_DEFAULT_SYNCHRONOUS - "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS), -#endif -#if SQLITE_DEFAULT_WAL_SYNCHRONOUS - "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS), -#endif -#if SQLITE_DIRECT_OVERFLOW_READ - "DIRECT_OVERFLOW_READ", -#endif #if SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif #if SQLITE_DISABLE_LFS "DISABLE_LFS", @@ -17584,13 +17365,10 @@ "ENABLE_UNLOCK_NOTIFY", #endif #if SQLITE_ENABLE_UPDATE_DELETE_LIMIT "ENABLE_UPDATE_DELETE_LIMIT", #endif -#if defined(SQLITE_ENABLE_URI_00_ERROR) - "ENABLE_URI_00_ERROR", -#endif #if SQLITE_HAS_CODEC "HAS_CODEC", #endif #if HAVE_ISNAN || SQLITE_HAVE_ISNAN "HAVE_ISNAN", @@ -17661,10 +17439,13 @@ #if SQLITE_OMIT_BLOB_LITERAL "OMIT_BLOB_LITERAL", #endif #if SQLITE_OMIT_BTREECOUNT "OMIT_BTREECOUNT", +#endif +#if SQLITE_OMIT_BUILTIN_TEST + "OMIT_BUILTIN_TEST", #endif #if SQLITE_OMIT_CAST "OMIT_CAST", #endif #if SQLITE_OMIT_CHECK @@ -17824,13 +17605,10 @@ "TEST", #endif #if defined(SQLITE_THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), #endif -#if SQLITE_UNTESTABLE - "UNTESTABLE" -#endif #if SQLITE_USE_ALLOCA "USE_ALLOCA", #endif #if SQLITE_USER_AUTHENTICATION "USER_AUTHENTICATION", @@ -17980,64 +17758,61 @@ ** * A virtual table ** * A one-row "pseudotable" stored in a single register */ typedef struct VdbeCursor VdbeCursor; struct VdbeCursor { - u8 eCurType; /* One of the CURTYPE_* values above */ - i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ - u8 nullRow; /* True if pointing to a row with no data */ - u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ - u8 isTable; /* True for rowid tables. False for indexes */ + u8 eCurType; /* One of the CURTYPE_* values above */ + i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ + u8 nullRow; /* True if pointing to a row with no data */ + u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ + u8 isTable; /* True for rowid tables. False for indexes */ #ifdef SQLITE_DEBUG - u8 seekOp; /* Most recent seek operation on this cursor */ - u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ + u8 seekOp; /* Most recent seek operation on this cursor */ + u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */ #endif - Bool isEphemeral:1; /* True for an ephemeral table */ - Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ - Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ - Btree *pBtx; /* Separate file holding temporary table */ - i64 seqCount; /* Sequence counter */ - int *aAltMap; /* Mapping from table to index column numbers */ - - /* Cached OP_Column parse information is only valid if cacheStatus matches - ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of - ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that - ** the cache is out of date. */ - u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ - int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0 - ** if there have been no prior seeks on the cursor. */ - /* NB: seekResult does not distinguish between "no seeks have ever occurred - ** on this cursor" and "the most recent seek was an exact match". */ - - /* When a new VdbeCursor is allocated, only the fields above are zeroed. - ** The fields that follow are uninitialized, and must be individually - ** initialized prior to first use. */ - VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ + Bool isEphemeral:1; /* True for an ephemeral table */ + Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */ + Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ + Pgno pgnoRoot; /* Root page of the open btree cursor */ + i16 nField; /* Number of fields in the header */ + u16 nHdrParsed; /* Number of header fields parsed so far */ union { BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */ int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */ } uc; - KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ - u32 iHdrOffset; /* Offset to next unparsed byte of the header */ - Pgno pgnoRoot; /* Root page of the open btree cursor */ - i16 nField; /* Number of fields in the header */ - u16 nHdrParsed; /* Number of header fields parsed so far */ - i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ - u32 *aOffset; /* Pointer to aType[nField] */ - const u8 *aRow; /* Data for the current row, if all on one page */ - u32 payloadSize; /* Total number of bytes in the record */ - u32 szRow; /* Byte available in aRow */ + Btree *pBt; /* Separate file holding temporary table */ + KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */ + int seekResult; /* Result of previous sqlite3BtreeMoveto() */ + i64 seqCount; /* Sequence counter */ + i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ + VdbeCursor *pAltCursor; /* Associated index cursor from which to read */ + int *aAltMap; /* Mapping from table to index column numbers */ #ifdef SQLITE_ENABLE_COLUMN_USED_MASK - u64 maskUsed; /* Mask of columns used by this cursor */ + u64 maskUsed; /* Mask of columns used by this cursor */ #endif + /* Cached information about the header for the data record that the + ** cursor is currently pointing to. Only valid if cacheStatus matches + ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of + ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that + ** the cache is out of date. + ** + ** aRow might point to (ephemeral) data for the current row, or it might + ** be NULL. + */ + u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */ + u32 payloadSize; /* Total number of bytes in the record */ + u32 szRow; /* Byte available in aRow */ + u32 iHdrOffset; /* Offset to next unparsed byte of the header */ + const u8 *aRow; /* Data for the current row, if all on one page */ + u32 *aOffset; /* Pointer to aType[nField] */ + u32 aType[1]; /* Type values for all entries in the record */ /* 2*nField extra array elements allocated for aType[], beyond the one ** static element declared in the structure. nField total array slots for ** aType[] and nField+1 array slots for aOffset[] */ - u32 aType[1]; /* Type values record decode. MUST BE LAST */ }; /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. @@ -18071,11 +17846,10 @@ VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ Op *aOp; /* Program instructions for parent frame */ i64 *anExec; /* Event counters from parent frame */ Mem *aMem; /* Array of memory cells for parent frame */ VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ - u8 *aOnce; /* Bitmask used by OP_Once */ void *token; /* Copy of SubProgram.token */ i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ AuxData *pAuxData; /* Linked list of auxdata allocations */ int nCursor; /* Number of entries in apCsr */ int pc; /* Program Counter in parent (calling) frame */ @@ -18254,10 +18028,11 @@ struct Vdbe { sqlite3 *db; /* The database connection that owns this statement */ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ Parse *pParse; /* Parsing context used to create this Vdbe */ ynVar nVar; /* Number of entries in aVar[] */ + ynVar nzVar; /* Number of entries in azVar[] */ u32 magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ int nCursor; /* Number of slots in apCsr[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ @@ -18278,11 +18053,11 @@ Mem *aColName; /* Column names to return */ Mem *pResultSet; /* Pointer to an array of results */ char *zErrMsg; /* Error message written here */ VdbeCursor **apCsr; /* One element of this array for each open cursor */ Mem *aVar; /* Values for the OP_Variable opcode. */ - VList *pVList; /* Name of variables */ + char **azVar; /* Name of variables */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif int nOp; /* Number of instructions in the program */ #ifdef SQLITE_DEBUG @@ -18342,11 +18117,10 @@ int iNewReg; /* Register for new.* values */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being upated */ - Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; /* ** Function prototypes */ @@ -18395,11 +18169,11 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8); -SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); +SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); SQLITE_PRIVATE const char *sqlite3OpcodeName(int); SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); @@ -18864,22 +18638,20 @@ /* ** A structure for holding a single date and time. */ typedef struct DateTime DateTime; struct DateTime { - sqlite3_int64 iJD; /* The julian day number times 86400000 */ - int Y, M, D; /* Year, month, and day */ - int h, m; /* Hour and minutes */ - int tz; /* Timezone offset in minutes */ - double s; /* Seconds */ - char validJD; /* True (1) if iJD is valid */ - char rawS; /* Raw numeric value stored in s */ - char validYMD; /* True (1) if Y,M,D are valid */ - char validHMS; /* True (1) if h,m,s are valid */ - char validTZ; /* True (1) if tz is valid */ - char tzSet; /* Timezone was set explicitly */ - char isError; /* An overflow has occurred */ + sqlite3_int64 iJD; /* The julian day number times 86400000 */ + int Y, M, D; /* Year, month, and day */ + int h, m; /* Hour and minutes */ + int tz; /* Timezone offset in minutes */ + double s; /* Seconds */ + char validYMD; /* True (1) if Y,M,D are valid */ + char validHMS; /* True (1) if h,m,s are valid */ + char validJD; /* True (1) if iJD is valid */ + char validTZ; /* True (1) if tz is valid */ + char tzSet; /* Timezone was set explicitly */ }; /* ** Convert zDate into one or more integers according to the conversion @@ -19023,28 +18795,19 @@ } }else{ s = 0; } p->validJD = 0; - p->rawS = 0; p->validHMS = 1; p->h = h; p->m = m; p->s = s + ms; if( parseTimezone(zDate, p) ) return 1; p->validTZ = (p->tz!=0)?1:0; return 0; } -/* -** Put the DateTime object into its error state. -*/ -static void datetimeError(DateTime *p){ - memset(p, 0, sizeof(*p)); - p->isError = 1; -} - /* ** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume ** that the YYYY-MM-DD is according to the Gregorian calendar. ** ** Reference: Meeus page 61 @@ -19060,14 +18823,10 @@ }else{ Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ M = 1; D = 1; } - if( Y<-4713 || Y>9999 || p->rawS ){ - datetimeError(p); - return; - } if( M<=2 ){ Y--; M += 12; } A = Y/100; @@ -19144,25 +18903,10 @@ }else{ return 1; } } -/* -** Input "r" is a numeric quantity which might be a julian day number, -** or the number of seconds since 1970. If the value if r is within -** range of a julian day number, install it as such and set validJD. -** If the value is a valid unix timestamp, put it in p->s and set p->rawS. -*/ -static void setRawDateNumber(DateTime *p, double r){ - p->s = r; - p->rawS = 1; - if( r>=0.0 && r<5373484.5 ){ - p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); - p->validJD = 1; - } -} - /* ** Attempt to parse the given string into a julian day number. Return ** the number of errors. ** ** The following are acceptable forms for the input string: @@ -19188,34 +18932,17 @@ }else if( parseHhMmSs(zDate, p)==0 ){ return 0; }else if( sqlite3StrICmp(zDate,"now")==0){ return setDateTimeToCurrent(context, p); }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){ - setRawDateNumber(p, r); + p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5); + p->validJD = 1; return 0; } return 1; } -/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999. -** Multiplying this by 86400000 gives 464269060799999 as the maximum value -** for DateTime.iJD. -** -** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with -** such a large integer literal, so we have to encode it. -*/ -#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff) - -/* -** Return TRUE if the given julian day number is within range. -** -** The input is the JulianDay times 86400000. -*/ -static int validJulianDay(sqlite3_int64 iJD){ - return iJD>=0 && iJD<=INT_464269060799999; -} - /* ** Compute the Year, Month, and Day from the julian day number. */ static void computeYMD(DateTime *p){ int Z, A, B, C, D, E, X1; @@ -19223,11 +18950,10 @@ if( !p->validJD ){ p->Y = 2000; p->M = 1; p->D = 1; }else{ - assert( validJulianDay(p->iJD) ); Z = (int)((p->iJD + 43200000)/86400000); A = (int)((Z - 1867216.25)/36524.25); A = Z + 1 + A - (A/4); B = A + 1524; C = (int)((B - 122.1)/365.25); @@ -19254,11 +18980,10 @@ p->s -= s; p->h = s/3600; s -= p->h*3600; p->m = s/60; p->s += s - p->m*60; - p->rawS = 0; p->validHMS = 1; } /* ** Compute both YMD and HMS @@ -19316,18 +19041,18 @@ #if SQLITE_THREADSAFE>0 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); pX = localtime(t); -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; #endif if( pX ) *pTm = *pX; sqlite3_mutex_leave(mutex); rc = pX==0; #else -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; #endif #if HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; #else @@ -19394,42 +19119,17 @@ y.m = sLocal.tm_min; y.s = sLocal.tm_sec; y.validYMD = 1; y.validHMS = 1; y.validJD = 0; - y.rawS = 0; y.validTZ = 0; - y.isError = 0; computeJD(&y); *pRc = SQLITE_OK; return y.iJD - x.iJD; } #endif /* SQLITE_OMIT_LOCALTIME */ -/* -** The following table defines various date transformations of the form -** -** 'NNN days' -** -** Where NNN is an arbitrary floating-point number and "days" can be one -** of several units of time. -*/ -static const struct { - u8 eType; /* Transformation type code */ - u8 nName; /* Length of th name */ - char *zName; /* Name of the transformation */ - double rLimit; /* Maximum NNN value for this transform */ - double rXform; /* Constant used for this transform */ -} aXformType[] = { - { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) }, - { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) }, - { 0, 4, "hour", 128963628.0, 86400000.0/24.0 }, - { 0, 3, "day", 5373485.0, 86400000.0 }, - { 1, 5, "month", 176546.0, 30.0*86400000.0 }, - { 2, 4, "year", 14713.0, 365.0*86400000.0 }, -}; - /* ** Process a modifier to a date-time stamp. The modifiers are ** as follows: ** ** NNN days @@ -19450,27 +19150,29 @@ ** Return 0 on success and 1 if there is any kind of error. If the error ** is in a system call (i.e. localtime()), then an error message is written ** to context pCtx. If the error is an unrecognized modifier, no error is ** written to pCtx. */ -static int parseModifier( - sqlite3_context *pCtx, /* Function context */ - const char *z, /* The text of the modifier */ - int n, /* Length of zMod in bytes */ - DateTime *p /* The date/time value to be modified */ -){ +static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){ int rc = 1; + int n; double r; - switch(sqlite3UpperToLower[(u8)z[0]] ){ + char *z, zBuf[30]; + z = zBuf; + for(n=0; niJD += localtimeOffset(p, pCtx, &rc); clearYMD_HMS_TZ(p); } break; @@ -19478,25 +19180,20 @@ #endif case 'u': { /* ** unixepoch ** - ** Treat the current value of p->s as the number of + ** Treat the current value of p->iJD as the number of ** seconds since 1970. Convert to a real julian day number. */ - if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){ - r = p->s*1000.0 + 210866760000000.0; - if( r>=0.0 && r<464269060800000.0 ){ - clearYMD_HMS_TZ(p); - p->iJD = (sqlite3_int64)r; - p->validJD = 1; - p->rawS = 0; - rc = 0; - } + if( strcmp(z, "unixepoch")==0 && p->validJD ){ + p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000; + clearYMD_HMS_TZ(p); + rc = 0; } #ifndef SQLITE_OMIT_LOCALTIME - else if( sqlite3_stricmp(z, "utc")==0 ){ + else if( strcmp(z, "utc")==0 ){ if( p->tzSet==0 ){ sqlite3_int64 c1; computeJD(p); c1 = localtimeOffset(p, pCtx, &rc); if( rc==SQLITE_OK ){ @@ -19518,11 +19215,11 @@ ** ** Move the date to the same time on the next occurrence of ** weekday N where 0==Sunday, 1==Monday, and so forth. If the ** date is already on the appropriate weekday, this is a no-op. */ - if( sqlite3_strnicmp(z, "weekday ", 8)==0 + if( strncmp(z, "weekday ", 8)==0 && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8) && (n=(int)r)==r && n>=0 && r<7 ){ sqlite3_int64 Z; computeYMD_HMS(p); p->validTZ = 0; @@ -19541,28 +19238,27 @@ ** start of TTTTT ** ** Move the date backwards to the beginning of the current day, ** or month or year. */ - if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break; - if( !p->validJD && !p->validYMD && !p->validHMS ) break; + if( strncmp(z, "start of ", 9)!=0 ) break; z += 9; computeYMD(p); p->validHMS = 1; p->h = p->m = 0; p->s = 0.0; - p->rawS = 0; p->validTZ = 0; p->validJD = 0; - if( sqlite3_stricmp(z,"month")==0 ){ + if( strcmp(z,"month")==0 ){ p->D = 1; rc = 0; - }else if( sqlite3_stricmp(z,"year")==0 ){ + }else if( strcmp(z,"year")==0 ){ + computeYMD(p); p->M = 1; p->D = 1; rc = 0; - }else if( sqlite3_stricmp(z,"day")==0 ){ + }else if( strcmp(z,"day")==0 ){ rc = 0; } break; } case '+': @@ -19576,11 +19272,10 @@ case '6': case '7': case '8': case '9': { double rRounder; - int i; for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){} if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){ rc = 1; break; } @@ -19605,52 +19300,50 @@ clearYMD_HMS_TZ(p); p->iJD += tx.iJD; rc = 0; break; } - - /* If control reaches this point, it means the transformation is - ** one of the forms like "+NNN days". */ z += n; while( sqlite3Isspace(*z) ) z++; n = sqlite3Strlen30(z); if( n>10 || n<3 ) break; - if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--; + if( z[n-1]=='s' ){ z[n-1] = 0; n--; } computeJD(p); - rc = 1; + rc = 0; rRounder = r<0 ? -0.5 : +0.5; - for(i=0; i-aXformType[i].rLimit && rM += (int)r; - x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; - p->Y += x; - p->M -= x*12; - p->validJD = 0; - r -= (int)r; - break; - } - case 2: { /* Special processing to add years */ - int y = (int)r; - computeYMD_HMS(p); - p->Y += y; - p->validJD = 0; - r -= (int)r; - break; - } - } - computeJD(p); - p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder); - rc = 0; - break; - } + if( n==3 && strcmp(z,"day")==0 ){ + p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder); + }else if( n==4 && strcmp(z,"hour")==0 ){ + p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder); + }else if( n==6 && strcmp(z,"minute")==0 ){ + p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder); + }else if( n==6 && strcmp(z,"second")==0 ){ + p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder); + }else if( n==5 && strcmp(z,"month")==0 ){ + int x, y; + computeYMD_HMS(p); + p->M += (int)r; + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + p->validJD = 0; + computeJD(p); + y = (int)r; + if( y!=r ){ + p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder); + } + }else if( n==4 && strcmp(z,"year")==0 ){ + int y = (int)r; + computeYMD_HMS(p); + p->Y += y; + p->validJD = 0; + computeJD(p); + if( y!=r ){ + p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder); + } + }else{ + rc = 1; } clearYMD_HMS_TZ(p); break; } default: { @@ -19673,33 +19366,31 @@ sqlite3_context *context, int argc, sqlite3_value **argv, DateTime *p ){ - int i, n; + int i; const unsigned char *z; int eType; memset(p, 0, sizeof(*p)); if( argc==0 ){ return setDateTimeToCurrent(context, p); } if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT || eType==SQLITE_INTEGER ){ - setRawDateNumber(p, sqlite3_value_double(argv[0])); + p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5); + p->validJD = 1; }else{ z = sqlite3_value_text(argv[0]); if( !z || parseDateOrTime(context, (char*)z, p) ){ return 1; } } for(i=1; iisError || !validJulianDay(p->iJD) ) return 1; return 0; } /* @@ -20493,11 +20184,11 @@ ** during a hash table resize is a benign fault. */ /* #include "sqliteInt.h" */ -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST /* ** Global variables. */ typedef struct BenignMallocHooks BenignMallocHooks; @@ -20551,11 +20242,11 @@ if( wsdHooks.xBenignEnd ){ wsdHooks.xBenignEnd(); } } -#endif /* #ifndef SQLITE_UNTESTABLE */ +#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */ /************** End of fault.c ***********************************************/ /************** Begin file mem0.c ********************************************/ /* ** 2008 October 28 @@ -20676,13 +20367,11 @@ ** Use the zone allocator available on apple products unless the ** SQLITE_WITHOUT_ZONEMALLOC symbol is defined. */ #include #include -#ifdef SQLITE_MIGHT_BE_SINGLE_CORE #include -#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */ static malloc_zone_t* _sqliteZone_; #define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x)) #define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x)); #define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y)) #define SQLITE_MALLOCSIZE(x) \ @@ -20746,22 +20435,20 @@ ** cases of nByte<=0 will be intercepted and dealt with by higher level ** routines. */ static void *sqlite3MemMalloc(int nByte){ #ifdef SQLITE_MALLOCSIZE - void *p; - testcase( ROUND8(nByte)==nByte ); - p = SQLITE_MALLOC( nByte ); + void *p = SQLITE_MALLOC( nByte ); if( p==0 ){ testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); } return p; #else sqlite3_int64 *p; assert( nByte>0 ); - testcase( ROUND8(nByte)!=nByte ); + nByte = ROUND8(nByte); p = SQLITE_MALLOC( nByte+8 ); if( p ){ p[0] = nByte; p++; }else{ @@ -20871,14 +20558,23 @@ /* defer MT decisions to system malloc */ _sqliteZone_ = malloc_default_zone(); }else{ /* only 1 core, use our own zone to contention over global locks, ** e.g. we have our own dedicated locks */ - _sqliteZone_ = malloc_create_zone(4096, 0); - malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap"); + bool success; + malloc_zone_t* newzone = malloc_create_zone(4096, 0); + malloc_set_zone_name(newzone, "Sqlite_Heap"); + do{ + success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, + (void * volatile *)&_sqliteZone_); + }while(!_sqliteZone_); + if( !success ){ + /* somebody registered a zone first */ + malloc_destroy_zone(newzone); + } } -#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */ +#endif UNUSED_PARAMETER(NotUsed); return SQLITE_OK; } /* @@ -23870,11 +23566,12 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); -#elif MSVC_VERSION>=1300 +#elif !defined(SQLITE_DISABLE_INTRINSIC) && \ + defined(_MSC_VER) && _MSC_VER>=1300 _ReadWriteBarrier(); #elif defined(MemoryBarrier) MemoryBarrier(); #endif } @@ -24081,12 +23778,12 @@ #ifdef SQLITE_DEBUG assert( p->nRef>0 || p->owner==0 ); p->owner = tid; p->nRef++; if( p->trace ){ - OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", - tid, p->id, p, p->trace, p->nRef)); + OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", + tid, p, p->trace, p->nRef)); } #endif } static int winMutexTry(sqlite3_mutex *p){ @@ -24124,12 +23821,12 @@ #else UNUSED_PARAMETER(p); #endif #ifdef SQLITE_DEBUG if( p->trace ){ - OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n", - tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); + OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n", + tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); } #endif return rc; } @@ -24153,12 +23850,12 @@ #endif assert( winMutex_isInit==1 ); LeaveCriticalSection(&p->mutex); #ifdef SQLITE_DEBUG if( p->trace ){ - OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", - tid, p->id, p, p->trace, p->nRef)); + OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", + tid, p, p->trace, p->nRef)); } #endif } SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ @@ -24402,30 +24099,15 @@ /* ** Do a memory allocation with statistics and alarms. Assume the ** lock is already held. */ -static void mallocWithAlarm(int n, void **pp){ - void *p; +static int mallocWithAlarm(int n, void **pp){ int nFull; + void *p; assert( sqlite3_mutex_held(mem0.mutex) ); - assert( n>0 ); - - /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal - ** implementation of malloc_good_size(), which must be called in debug - ** mode and specifically when the DMD "Dark Matter Detector" is enabled - ** or else a crash results. Hence, do not attempt to optimize out the - ** following xRoundup() call. */ nFull = sqlite3GlobalConfig.m.xRoundup(n); - -#ifdef SQLITE_MAX_MEMORY - if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){ - *pp = 0; - return; - } -#endif - sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n); if( mem0.alarmThreshold>0 ){ sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); if( nUsed >= mem0.alarmThreshold - nFull ){ mem0.nearlyFull = 1; @@ -24445,10 +24127,11 @@ nFull = sqlite3MallocSize(p); sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); } *pp = p; + return nFull; } /* ** Allocate memory. This routine is like sqlite3_malloc() except that it ** assumes the memory subsystem has already been initialized. @@ -24610,11 +24293,11 @@ return sqlite3GlobalConfig.m.xSize(p); } SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){ assert( p!=0 ); if( db==0 || !isLookaside(db,p) ){ -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG if( db==0 ){ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); }else{ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); @@ -24671,11 +24354,11 @@ measureAllocationSize(db, p); return; } if( isLookaside(db, p) ){ LookasideSlot *pBuf = (LookasideSlot*)p; -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG /* Trash all content in the buffer being freed */ memset(p, 0xaa, db->lookaside.sz); #endif pBuf->pNext = db->lookaside.pFree; db->lookaside.pFree = pBuf; @@ -24718,11 +24401,11 @@ pNew = pOld; }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes); nDiff = nNew - nOld; - if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= + if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= mem0.alarmThreshold-nDiff ){ sqlite3MallocAlarm(nDiff); } pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); if( pNew==0 && mem0.alarmThreshold>0 ){ @@ -24925,12 +24608,13 @@ char *zNew; size_t n; if( z==0 ){ return 0; } - n = strlen(z) + 1; - zNew = sqlite3DbMallocRaw(db, n); + n = sqlite3Strlen30(z) + 1; + assert( (n&0x7fffffff)==n ); + zNew = sqlite3DbMallocRaw(db, (int)n); if( zNew ){ memcpy(zNew, z, n); } return zNew; } @@ -25040,11 +24724,11 @@ /* ** Conversion types fall into various categories as defined by the ** following enumeration. */ -#define etRADIX 0 /* non-decimal integer types. %x %o */ +#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */ #define etFLOAT 1 /* Floating point. %f */ #define etEXP 2 /* Exponentional notation. %e and %E */ #define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ #define etSIZE 4 /* Return number of characters processed so far. %n */ #define etSTRING 5 /* Strings. %s */ @@ -25058,13 +24742,12 @@ #define etTOKEN 11 /* a pointer to a Token structure */ #define etSRCLIST 12 /* a pointer to a SrcList */ #define etPOINTER 13 /* The %p conversion */ #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ -#define etDECIMAL 16 /* %d or %u, but not %x, %o */ -#define etINVALID 17 /* Any unrecognized conversion type */ +#define etINVALID 16 /* Any unrecognized conversion type */ /* ** An "etByte" is an 8-bit unsigned value. */ @@ -25084,48 +24767,50 @@ } et_info; /* ** Allowed values for et_info.flags */ -#define FLAG_SIGNED 1 /* True if the value to convert is signed */ -#define FLAG_STRING 4 /* Allow infinite precision */ +#define FLAG_SIGNED 1 /* True if the value to convert is signed */ +#define FLAG_INTERN 2 /* True if for internal use only */ +#define FLAG_STRING 4 /* Allow infinity precision */ /* ** The following table is searched linearly, so it is good to put the ** most frequently used conversion types first. */ static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aPrefix[] = "-x0\000X0"; static const et_info fmtinfo[] = { - { 'd', 10, 1, etDECIMAL, 0, 0 }, + { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, { 'g', 0, 1, etGENERIC, 30, 0 }, { 'z', 0, 4, etDYNSTRING, 0, 0 }, { 'q', 0, 4, etSQLESCAPE, 0, 0 }, { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, 0, 2 }, - { 'u', 10, 0, etDECIMAL, 0, 0 }, + { 'u', 10, 0, etRADIX, 0, 0 }, { 'x', 16, 0, etRADIX, 16, 1 }, { 'X', 16, 0, etRADIX, 0, 4 }, #ifndef SQLITE_OMIT_FLOATING_POINT { 'f', 0, 1, etFLOAT, 0, 0 }, { 'e', 0, 1, etEXP, 30, 0 }, { 'E', 0, 1, etEXP, 14, 0 }, { 'G', 0, 1, etGENERIC, 14, 0 }, #endif - { 'i', 10, 1, etDECIMAL, 0, 0 }, + { 'i', 10, 1, etRADIX, 0, 0 }, { 'n', 0, 0, etSIZE, 0, 0 }, { '%', 0, 0, etPERCENT, 0, 0 }, { 'p', 16, 0, etPOINTER, 0, 1 }, - /* All the rest are undocumented and are for internal use only */ - { 'T', 0, 0, etTOKEN, 0, 0 }, - { 'S', 0, 0, etSRCLIST, 0, 0 }, - { 'r', 10, 1, etORDINAL, 0, 0 }, +/* All the rest have the FLAG_INTERN bit set and are thus for internal +** use only */ + { 'T', 0, 2, etTOKEN, 0, 0 }, + { 'S', 0, 2, etSRCLIST, 0, 0 }, + { 'r', 10, 3, etORDINAL, 0, 0 }, }; /* ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point ** conversions will work. @@ -25205,19 +24890,21 @@ int precision; /* Precision of the current field */ int length; /* Length of the field */ int idx; /* A general purpose loop counter */ int width; /* Width of the current field */ etByte flag_leftjustify; /* True if "-" flag is present */ - etByte flag_prefix; /* '+' or ' ' or 0 for prefix */ + etByte flag_plussign; /* True if "+" flag is present */ + etByte flag_blanksign; /* True if " " flag is present */ etByte flag_alternateform; /* True if "#" flag is present */ etByte flag_altform2; /* True if "!" flag is present */ etByte flag_zeropad; /* True if field width constant starts with zero */ - etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */ + etByte flag_long; /* True if "l" flag is present */ + etByte flag_longlong; /* True if the "ll" flag is present */ etByte done; /* Loop termination flag */ - etByte cThousand; /* Thousands separator for %d and %u */ etByte xtype = etINVALID; /* Conversion paradigm */ u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ + u8 useIntern; /* Ok to use internal conversions (ex: %T) */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ const et_info *infop; /* Pointer to the appropriate info structure */ char *zOut; /* Rendering buffer */ @@ -25232,15 +24919,17 @@ #endif PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ bufpt = 0; - if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ - pArgList = va_arg(ap, PrintfArguments*); - bArgList = 1; + if( pAccum->printfFlags ){ + if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ + pArgList = va_arg(ap, PrintfArguments*); + } + useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL; }else{ - bArgList = 0; + bArgList = useIntern = 0; } for(; (c=(*fmt))!=0; ++fmt){ if( c!='%' ){ bufpt = (char *)fmt; #if HAVE_STRCHRNUL @@ -25254,22 +24943,21 @@ if( (c=(*++fmt))==0 ){ sqlite3StrAccumAppend(pAccum, "%", 1); break; } /* Find out what flags are present */ - flag_leftjustify = flag_prefix = cThousand = + flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_altform2 = flag_zeropad = 0; done = 0; do{ switch( c ){ case '-': flag_leftjustify = 1; break; - case '+': flag_prefix = '+'; break; - case ' ': flag_prefix = ' '; break; + case '+': flag_plussign = 1; break; + case ' ': flag_blanksign = 1; break; case '#': flag_alternateform = 1; break; case '!': flag_altform2 = 1; break; case '0': flag_zeropad = 1; break; - case ',': cThousand = ','; break; default: done = 1; break; } }while( !done && (c=(*++fmt))!=0 ); /* Get the field width */ if( c=='*' ){ @@ -25335,64 +25023,69 @@ /* Get the conversion type modifier */ if( c=='l' ){ flag_long = 1; c = *++fmt; if( c=='l' ){ - flag_long = 2; + flag_longlong = 1; c = *++fmt; + }else{ + flag_longlong = 0; } }else{ - flag_long = 0; + flag_long = flag_longlong = 0; } /* Fetch the info entry for the field */ infop = &fmtinfo[0]; xtype = etINVALID; for(idx=0; idxtype; + if( useIntern || (infop->flags & FLAG_INTERN)==0 ){ + xtype = infop->type; + }else{ + return; + } break; } } /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. ** flag_altform2 TRUE if a '!' is present. - ** flag_prefix '+' or ' ' or zero + ** flag_plussign TRUE if a '+' is present. ** flag_leftjustify TRUE if a '-' is present or if the ** field width was negative. ** flag_zeropad TRUE if the width began with 0. - ** flag_long 1 for "l", 2 for "ll" + ** flag_long TRUE if the letter 'l' (ell) prefixed + ** the conversion character. + ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed + ** the conversion character. + ** flag_blanksign TRUE if a ' ' is present. ** width The specified field width. This is ** always non-negative. Zero is the default. ** precision The specified precision. The default ** is -1. ** xtype The class of the conversion. ** infop Pointer to the appropriate info struct. */ switch( xtype ){ case etPOINTER: - flag_long = sizeof(char*)==sizeof(i64) ? 2 : - sizeof(char*)==sizeof(long int) ? 1 : 0; + flag_longlong = sizeof(char*)==sizeof(i64); + flag_long = sizeof(char*)==sizeof(long int); /* Fall through into the next case */ case etORDINAL: - case etRADIX: - cThousand = 0; - /* Fall through into the next case */ - case etDECIMAL: + case etRADIX: if( infop->flags & FLAG_SIGNED ){ i64 v; if( bArgList ){ v = getIntArg(pArgList); + }else if( flag_longlong ){ + v = va_arg(ap,i64); }else if( flag_long ){ - if( flag_long==2 ){ - v = va_arg(ap,i64) ; - }else{ - v = va_arg(ap,long int); - } + v = va_arg(ap,long int); }else{ v = va_arg(ap,int); } if( v<0 ){ if( v==SMALLEST_INT64 ){ @@ -25401,41 +25094,40 @@ longvalue = -v; } prefix = '-'; }else{ longvalue = v; - prefix = flag_prefix; + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; } }else{ if( bArgList ){ longvalue = (u64)getIntArg(pArgList); + }else if( flag_longlong ){ + longvalue = va_arg(ap,u64); }else if( flag_long ){ - if( flag_long==2 ){ - longvalue = va_arg(ap,u64); - }else{ - longvalue = va_arg(ap,unsigned long int); - } + longvalue = va_arg(ap,unsigned long int); }else{ longvalue = va_arg(ap,unsigned int); } prefix = 0; } if( longvalue==0 ) flag_alternateform = 0; if( flag_zeropad && precision0 ); } length = (int)(&zOut[nOut-1]-bufpt); - while( precision>length ){ + for(idx=precision-length; idx>0; idx--){ *(--bufpt) = '0'; /* Zero pad */ - length++; - } - if( cThousand ){ - int nn = (length - 1)/3; /* Number of "," to insert */ - int ix = (length - 1)%3 + 1; - bufpt -= nn; - for(idx=0; nn>0; idx++){ - bufpt[idx] = bufpt[idx+nn]; - ix--; - if( ix==0 ){ - bufpt[++idx] = cThousand; - nn--; - ix = 3; - } - } } if( prefix ) *(--bufpt) = prefix; /* Add sign */ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ const char *pre; char x; @@ -25495,11 +25172,13 @@ if( precision<0 ) precision = 6; /* Set default precision */ if( realvalue<0.0 ){ realvalue = -realvalue; prefix = '-'; }else{ - prefix = flag_prefix; + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; } if( xtype==etGENERIC && precision>0 ) precision--; testcase( precision>0xfff ); for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} if( xtype==etFLOAT ) realvalue += rounder; @@ -25731,28 +25410,22 @@ ** consume, not the length of the output... ** if( precision>=0 && precisionprintfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - pToken = va_arg(ap, Token*); + Token *pToken = va_arg(ap, Token*); assert( bArgList==0 ); if( pToken && pToken->n ){ sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); } length = width = 0; break; } case etSRCLIST: { - SrcList *pSrc; - int k; - struct SrcList_item *pItem; - if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - pSrc = va_arg(ap, SrcList*); - k = va_arg(ap, int); - pItem = &pSrc->a[k]; + SrcList *pSrc = va_arg(ap, SrcList*); + int k = va_arg(ap, int); + struct SrcList_item *pItem = &pSrc->a[k]; assert( bArgList==0 ); assert( k>=0 && knSrc ); if( pItem->zDatabase ){ sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); sqlite3StrAccumAppend(pAccum, ".", 1); @@ -25770,17 +25443,13 @@ ** The text of the conversion is pointed to by "bufpt" and is ** "length" characters long. The field width is "width". Do ** the output. */ width -= length; - if( width>0 ){ - if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); - sqlite3StrAccumAppend(pAccum, bufpt, length); - if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); - }else{ - sqlite3StrAccumAppend(pAccum, bufpt, length); - } + if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); + sqlite3StrAccumAppend(pAccum, bufpt, length); + if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); if( zExtra ){ sqlite3DbFree(pAccum->db, zExtra); zExtra = 0; } @@ -25881,11 +25550,11 @@ assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); assert( p->accError==0 || p->nAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); - }else if( N ){ + }else{ assert( p->zText ); p->nChar += N; memcpy(&p->zText[p->nChar-N], z, N); } } @@ -25901,27 +25570,22 @@ /* ** Finish off a string by making sure it is zero-terminated. ** Return a pointer to the resulting string. Return a NULL ** pointer if any kind of error was encountered. */ -static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ - assert( p->mxAlloc>0 && !isMalloced(p) ); - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); - if( p->zText ){ - memcpy(p->zText, p->zBase, p->nChar+1); - p->printfFlags |= SQLITE_PRINTF_MALLOCED; - }else{ - setStrAccumError(p, STRACCUM_NOMEM); - } - return p->zText; -} SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ assert( (p->zText==p->zBase)==!isMalloced(p) ); p->zText[p->nChar] = 0; if( p->mxAlloc>0 && !isMalloced(p) ){ - return strAccumFinishRealloc(p); + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); + if( p->zText ){ + memcpy(p->zText, p->zBase, p->nChar+1); + p->printfFlags |= SQLITE_PRINTF_MALLOCED; + }else{ + setStrAccumError(p, STRACCUM_NOMEM); + } } } return p->zText; } @@ -26057,12 +25721,11 @@ return zBuf; } #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3VXPrintf(&acc, zFormat, ap); - zBuf[acc.nChar] = 0; - return zBuf; + return sqlite3StrAccumFinish(&acc); } SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); @@ -26206,11 +25869,10 @@ sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); } va_start(ap, zFormat); sqlite3VXPrintf(&acc, zFormat, ap); va_end(ap); - assert( acc.nChar>0 ); if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); sqlite3StrAccumFinish(&acc); fprintf(stdout,"%s", zBuf); fflush(stdout); } @@ -26267,14 +25929,10 @@ ** Generate a human-readable description of a Select object. */ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; int cnt = 0; - if( p==0 ){ - sqlite3TreeViewLine(pView, "nil-SELECT"); - return; - } pView = sqlite3TreeViewPush(pView, moreToFollow); if( p->pWith ){ sqlite3TreeViewWith(pView, p->pWith, 1); cnt = 1; sqlite3TreeViewPush(pView, 1); @@ -26771,11 +26429,11 @@ *(zBuf++) = wsdPrng.s[t]; }while( --N ); sqlite3_mutex_leave(mutex); } -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST /* ** For testing purposes, we sometimes want to preserve the state of ** PRNG and restore the PRNG to its saved state at a later time, or ** to reset the PRNG to its initial state. These routines accomplish ** those tasks. @@ -26796,11 +26454,11 @@ &GLOBAL(struct sqlite3PrngType, sqlite3Prng), &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), sizeof(sqlite3Prng) ); } -#endif /* SQLITE_UNTESTABLE */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ /************** End of random.c **********************************************/ /************** Begin file threads.c *****************************************/ /* ** 2012 July 21 @@ -27654,11 +27312,11 @@ ** which of multiple sqlite3FaultSim() calls has been hit. ** ** Return whatever integer value the test callback returns, or return ** SQLITE_OK if no test callback is installed. */ -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback; return xCallback ? xCallback(iTest) : SQLITE_OK; } #endif @@ -28752,15 +28410,17 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){ #if SQLITE_BYTEORDER==4321 u32 x; memcpy(&x,p,4); return x; -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(__GNUC__) && GCC_VERSION>=4003000 u32 x; memcpy(&x,p,4); return __builtin_bswap32(x); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(_MSC_VER) && _MSC_VER>=1300 u32 x; memcpy(&x,p,4); return _byteswap_ulong(x); #else testcase( p[0]&0x80 ); @@ -28768,14 +28428,16 @@ #endif } SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){ #if SQLITE_BYTEORDER==4321 memcpy(p,&v,4); -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(__GNUC__) && GCC_VERSION>=4003000 u32 x = __builtin_bswap32(v); memcpy(p,&x,4); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(_MSC_VER) && _MSC_VER>=1300 u32 x = _byteswap_ulong(v); memcpy(p,&x,4); #else p[0] = (u8)(v>>24); p[1] = (u8)(v>>16); @@ -28887,13 +28549,10 @@ ** the other 64-bit signed integer at *pA and store the result in *pA. ** Return 0 on success. Or if the operation would have resulted in an ** overflow, leave *pA unchanged and return 1. */ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 - return __builtin_add_overflow(*pA, iB, pA); -#else i64 iA = *pA; testcase( iA==0 ); testcase( iA==1 ); testcase( iB==-1 ); testcase( iB==0 ); if( iB>=0 ){ testcase( iA>0 && LARGEST_INT64 - iA == iB ); @@ -28904,31 +28563,23 @@ testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 ); if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1; } *pA += iB; return 0; -#endif } SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 - return __builtin_sub_overflow(*pA, iB, pA); -#else testcase( iB==SMALLEST_INT64+1 ); if( iB==SMALLEST_INT64 ){ testcase( (*pA)==(-1) ); testcase( (*pA)==0 ); if( (*pA)>=0 ) return 1; *pA -= iB; return 0; }else{ return sqlite3AddInt64(pA, -iB); } -#endif } SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 - return __builtin_mul_overflow(*pA, iB, pA); -#else i64 iA = *pA; if( iB>0 ){ if( iA>LARGEST_INT64/iB ) return 1; if( iALARGEST_INT64/-iB ) return 1; } } *pA = iA*iB; return 0; -#endif } /* ** Compute the absolute value of a 32-bit signed integer, of possible. Or ** if the integer has a value of -2147483648, return +2147483647 @@ -29074,113 +28724,10 @@ #endif return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x); } #endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ -/* -** Add a new name/number pair to a VList. This might require that the -** VList object be reallocated, so return the new VList. If an OOM -** error occurs, the original VList returned and the -** db->mallocFailed flag is set. -** -** A VList is really just an array of integers. To destroy a VList, -** simply pass it to sqlite3DbFree(). -** -** The first integer is the number of integers allocated for the whole -** VList. The second integer is the number of integers actually used. -** Each name/number pair is encoded by subsequent groups of 3 or more -** integers. -** -** Each name/number pair starts with two integers which are the numeric -** value for the pair and the size of the name/number pair, respectively. -** The text name overlays one or more following integers. The text name -** is always zero-terminated. -** -** Conceptually: -** -** struct VList { -** int nAlloc; // Number of allocated slots -** int nUsed; // Number of used slots -** struct VListEntry { -** int iValue; // Value for this entry -** int nSlot; // Slots used by this entry -** // ... variable name goes here -** } a[0]; -** } -** -** During code generation, pointers to the variable names within the -** VList are taken. When that happens, nAlloc is set to zero as an -** indication that the VList may never again be enlarged, since the -** accompanying realloc() would invalidate the pointers. -*/ -SQLITE_PRIVATE VList *sqlite3VListAdd( - sqlite3 *db, /* The database connection used for malloc() */ - VList *pIn, /* The input VList. Might be NULL */ - const char *zName, /* Name of symbol to add */ - int nName, /* Bytes of text in zName */ - int iVal /* Value to associate with zName */ -){ - int nInt; /* number of sizeof(int) objects needed for zName */ - char *z; /* Pointer to where zName will be stored */ - int i; /* Index in pIn[] where zName is stored */ - - nInt = nName/4 + 3; - assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */ - if( pIn==0 || pIn[1]+nInt > pIn[0] ){ - /* Enlarge the allocation */ - int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt; - VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int)); - if( pOut==0 ) return pIn; - if( pIn==0 ) pOut[1] = 2; - pIn = pOut; - pIn[0] = nAlloc; - } - i = pIn[1]; - pIn[i] = iVal; - pIn[i+1] = nInt; - z = (char*)&pIn[i+2]; - pIn[1] = i+nInt; - assert( pIn[1]<=pIn[0] ); - memcpy(z, zName, nName); - z[nName] = 0; - return pIn; -} - -/* -** Return a pointer to the name of a variable in the given VList that -** has the value iVal. Or return a NULL if there is no such variable in -** the list -*/ -SQLITE_PRIVATE const char *sqlite3VListNumToName(VList *pIn, int iVal){ - int i, mx; - if( pIn==0 ) return 0; - mx = pIn[1]; - i = 2; - do{ - if( pIn[i]==iVal ) return (char*)&pIn[i+2]; - i += pIn[i+1]; - }while( i0 then r[P1]-=P3, goto P2"), - /* 68 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"), - /* 69 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), - /* 70 */ "IncrVacuum" OpHelp(""), - /* 71 */ "VNext" OpHelp(""), - /* 72 */ "Init" OpHelp("Start at P2"), - /* 73 */ "Return" OpHelp(""), - /* 74 */ "EndCoroutine" OpHelp(""), - /* 75 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 76 */ "Halt" OpHelp(""), - /* 77 */ "Integer" OpHelp("r[P2]=P1"), - /* 78 */ "Int64" OpHelp("r[P2]=P4"), - /* 79 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 80 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 81 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 82 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 83 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 84 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 85 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 86 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 87 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 88 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 89 */ "CollSeq" OpHelp(""), - /* 90 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 91 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 92 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 93 */ "RealAffinity" OpHelp(""), - /* 94 */ "Cast" OpHelp("affinity(r[P1])"), - /* 95 */ "Permutation" OpHelp(""), - /* 96 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 55 */ "SorterSort" OpHelp(""), + /* 56 */ "Sort" OpHelp(""), + /* 57 */ "Rewind" OpHelp(""), + /* 58 */ "IdxLE" OpHelp("key=r[P3@P4]"), + /* 59 */ "IdxGT" OpHelp("key=r[P3@P4]"), + /* 60 */ "IdxLT" OpHelp("key=r[P3@P4]"), + /* 61 */ "IdxGE" OpHelp("key=r[P3@P4]"), + /* 62 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"), + /* 63 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"), + /* 64 */ "Program" OpHelp(""), + /* 65 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"), + /* 66 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"), + /* 67 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"), + /* 68 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), + /* 69 */ "IncrVacuum" OpHelp(""), + /* 70 */ "VNext" OpHelp(""), + /* 71 */ "Init" OpHelp("Start at P2"), + /* 72 */ "Return" OpHelp(""), + /* 73 */ "EndCoroutine" OpHelp(""), + /* 74 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 75 */ "Halt" OpHelp(""), + /* 76 */ "Integer" OpHelp("r[P2]=P1"), + /* 77 */ "Int64" OpHelp("r[P2]=P4"), + /* 78 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 79 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 80 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 81 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 82 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 83 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 84 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 85 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 86 */ "IntCopy" OpHelp("r[P2]=r[P1]"), + /* 87 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 88 */ "CollSeq" OpHelp(""), + /* 89 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 90 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 91 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 92 */ "RealAffinity" OpHelp(""), + /* 93 */ "Cast" OpHelp("affinity(r[P1])"), + /* 94 */ "Permutation" OpHelp(""), + /* 95 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 96 */ "Column" OpHelp("r[P3]=PX"), /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "Column" OpHelp("r[P3]=PX"), - /* 99 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 100 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 101 */ "Count" OpHelp("r[P2]=count()"), - /* 102 */ "ReadCookie" OpHelp(""), - /* 103 */ "SetCookie" OpHelp(""), - /* 104 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 105 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 106 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 107 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 108 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 109 */ "SorterOpen" OpHelp(""), - /* 110 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 111 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 112 */ "Close" OpHelp(""), - /* 113 */ "ColumnsUsed" OpHelp(""), - /* 114 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 115 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 116 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 117 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 118 */ "Delete" OpHelp(""), - /* 119 */ "ResetCount" OpHelp(""), - /* 120 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 121 */ "SorterData" OpHelp("r[P2]=data"), + /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 100 */ "Count" OpHelp("r[P2]=count()"), + /* 101 */ "ReadCookie" OpHelp(""), + /* 102 */ "SetCookie" OpHelp(""), + /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 106 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 107 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 108 */ "SorterOpen" OpHelp(""), + /* 109 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 110 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 111 */ "Close" OpHelp(""), + /* 112 */ "ColumnsUsed" OpHelp(""), + /* 113 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 114 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 115 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 116 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 117 */ "Delete" OpHelp(""), + /* 118 */ "ResetCount" OpHelp(""), + /* 119 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 120 */ "SorterData" OpHelp("r[P2]=data"), + /* 121 */ "RowKey" OpHelp("r[P2]=key"), /* 122 */ "RowData" OpHelp("r[P2]=data"), /* 123 */ "Rowid" OpHelp("r[P2]=rowid"), /* 124 */ "NullRow" OpHelp(""), - /* 125 */ "SorterInsert" OpHelp("key=r[P2]"), + /* 125 */ "SorterInsert" OpHelp(""), /* 126 */ "IdxInsert" OpHelp("key=r[P2]"), /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"), /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"), /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"), /* 130 */ "Destroy" OpHelp(""), @@ -29601,38 +29148,37 @@ /* 131 */ "Clear" OpHelp(""), /* 132 */ "Real" OpHelp("r[P2]=P4"), /* 133 */ "ResetSorter" OpHelp(""), /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"), /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"), - /* 136 */ "SqlExec" OpHelp(""), - /* 137 */ "ParseSchema" OpHelp(""), - /* 138 */ "LoadAnalysis" OpHelp(""), - /* 139 */ "DropTable" OpHelp(""), - /* 140 */ "DropIndex" OpHelp(""), - /* 141 */ "DropTrigger" OpHelp(""), - /* 142 */ "IntegrityCk" OpHelp(""), - /* 143 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 144 */ "Param" OpHelp(""), - /* 145 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 146 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 147 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 148 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 149 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 150 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 151 */ "Expire" OpHelp(""), - /* 152 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 153 */ "VBegin" OpHelp(""), - /* 154 */ "VCreate" OpHelp(""), - /* 155 */ "VDestroy" OpHelp(""), - /* 156 */ "VOpen" OpHelp(""), - /* 157 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 158 */ "VRename" OpHelp(""), - /* 159 */ "Pagecount" OpHelp(""), - /* 160 */ "MaxPgcnt" OpHelp(""), - /* 161 */ "CursorHint" OpHelp(""), - /* 162 */ "Noop" OpHelp(""), - /* 163 */ "Explain" OpHelp(""), + /* 136 */ "ParseSchema" OpHelp(""), + /* 137 */ "LoadAnalysis" OpHelp(""), + /* 138 */ "DropTable" OpHelp(""), + /* 139 */ "DropIndex" OpHelp(""), + /* 140 */ "DropTrigger" OpHelp(""), + /* 141 */ "IntegrityCk" OpHelp(""), + /* 142 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 143 */ "Param" OpHelp(""), + /* 144 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 145 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 146 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 147 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 148 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 149 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 150 */ "Expire" OpHelp(""), + /* 151 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 152 */ "VBegin" OpHelp(""), + /* 153 */ "VCreate" OpHelp(""), + /* 154 */ "VDestroy" OpHelp(""), + /* 155 */ "VOpen" OpHelp(""), + /* 156 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 157 */ "VRename" OpHelp(""), + /* 158 */ "Pagecount" OpHelp(""), + /* 159 */ "MaxPgcnt" OpHelp(""), + /* 160 */ "CursorHint" OpHelp(""), + /* 161 */ "Noop" OpHelp(""), + /* 162 */ "Explain" OpHelp(""), }; return azName[i]; } #endif @@ -30897,18 +30443,11 @@ struct unixFileId { dev_t dev; /* Device number */ #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID for vxworks. */ #else - /* We are told that some versions of Android contain a bug that - ** sizes ino_t at only 32-bits instead of 64-bits. (See - ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c) - ** To work around this, always allocate 64-bits for the inode number. - ** On small machines that only have 32-bit inodes, this wastes 4 bytes, - ** but that should not be a big deal. */ - /* WAS: ino_t ino; */ - u64 ino; /* Inode number */ + ino_t ino; /* Inode number */ #endif }; /* ** An instance of the following structure is allocated for each open @@ -31149,11 +30688,11 @@ memset(&fileId, 0, sizeof(fileId)); fileId.dev = statbuf.st_dev; #if OS_VXWORKS fileId.pId = pFile->pId; #else - fileId.ino = (u64)statbuf.st_ino; + fileId.ino = statbuf.st_ino; #endif pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ pInode = pInode->pNext; } @@ -31183,12 +30722,11 @@ #if OS_VXWORKS return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId; #else struct stat buf; return pFile->pInode!=0 && - (osStat(pFile->zPath, &buf)!=0 - || (u64)buf.st_ino!=pFile->pInode->fileId.ino); + (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino); #endif } /* @@ -35356,11 +34894,11 @@ unixInodeInfo *pInode; unixEnterMutex(); pInode = inodeList; while( pInode && (pInode->fileId.dev!=sStat.st_dev - || pInode->fileId.ino!=(u64)sStat.st_ino) ){ + || pInode->fileId.ino!=sStat.st_ino) ){ pInode = pInode->pNext; } if( pInode ){ UnixUnusedFd **pp; for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); @@ -38010,84 +37548,46 @@ * be freed immediately and any attempt to access any of that freed * data will almost certainly result in an immediate access violation. ****************************************************************************** */ #ifndef SQLITE_WIN32_HEAP_CREATE -# define SQLITE_WIN32_HEAP_CREATE (TRUE) -#endif - -/* - * This is the maximum possible initial size of the Win32-specific heap, in - * bytes. - */ -#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE -# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U) -#endif - -/* - * This is the extra space for the initial size of the Win32-specific heap, - * in bytes. This value may be zero. - */ -#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA -# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304) -#endif - -/* - * Calculate the maximum legal cache size, in pages, based on the maximum - * possible initial heap size and the default page size, setting aside the - * needed extra space. - */ -#ifndef SQLITE_WIN32_MAX_CACHE_SIZE -# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \ - (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \ - (SQLITE_DEFAULT_PAGE_SIZE)) +# define SQLITE_WIN32_HEAP_CREATE (TRUE) #endif /* * This is cache size used in the calculation of the initial size of the * Win32-specific heap. It cannot be negative. */ #ifndef SQLITE_WIN32_CACHE_SIZE # if SQLITE_DEFAULT_CACHE_SIZE>=0 -# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) +# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE) # else -# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) +# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE)) # endif #endif -/* - * Make sure that the calculated cache size, in pages, cannot cause the - * initial size of the Win32-specific heap to exceed the maximum amount - * of memory that can be specified in the call to HeapCreate. - */ -#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE -# undef SQLITE_WIN32_CACHE_SIZE -# define SQLITE_WIN32_CACHE_SIZE (2000) -#endif - /* * The initial size of the Win32-specific heap. This value may be zero. */ #ifndef SQLITE_WIN32_HEAP_INIT_SIZE -# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ - (SQLITE_DEFAULT_PAGE_SIZE) + \ - (SQLITE_WIN32_HEAP_INIT_EXTRA)) +# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \ + (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) #endif /* * The maximum size of the Win32-specific heap. This value may be zero. */ #ifndef SQLITE_WIN32_HEAP_MAX_SIZE -# define SQLITE_WIN32_HEAP_MAX_SIZE (0) +# define SQLITE_WIN32_HEAP_MAX_SIZE (0) #endif /* * The extra flags to use in calls to the Win32 heap APIs. This value may be * zero for the default behavior. */ #ifndef SQLITE_WIN32_HEAP_FLAGS -# define SQLITE_WIN32_HEAP_FLAGS (0) +# define SQLITE_WIN32_HEAP_FLAGS (0) #endif /* ** The winMemData structure stores information required by the Win32-specific @@ -43955,11 +43455,11 @@ */ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){ return p->iSize; } -#ifndef SQLITE_UNTESTABLE +#ifndef SQLITE_OMIT_BUILTIN_TEST /* ** Let V[] be an array of unsigned characters sufficient to hold ** up to N bits. Let I be an integer between 0 and N. 0<=Ipgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */ + assert( pPg->pgno>0 ); /* Page number is 1 or more */ pCache = pPg->pCache; assert( pCache!=0 ); /* Every page has an associated PCache */ if( pPg->flags & PGHDR_CLEAN ){ assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */ @@ -44360,16 +43860,10 @@ /* ** Create a new PCache object. Storage space to hold the object ** has already been allocated and is passed in as the p pointer. ** The caller discovers how much space needs to be allocated by ** calling sqlite3PcacheSize(). -** -** szExtra is some extra space allocated for each page. The first -** 8 bytes of the extra space will be zeroed as the page is allocated, -** but remaining content will be uninitialized. Though it is opaque -** to this module, the extra space really ends up being the MemPage -** structure in the pager. */ SQLITE_PRIVATE int sqlite3PcacheOpen( int szPage, /* Size of every page */ int szExtra, /* Extra space associated with each page */ int bPurgeable, /* True if pages are on backing store */ @@ -44378,11 +43872,10 @@ PCache *p /* Preallocated space for the PCache */ ){ memset(p, 0, sizeof(PCache)); p->szPage = 1; p->szExtra = szExtra; - assert( szExtra>=8 ); /* First 8 bytes will be zeroed */ p->bPurgeable = bPurgeable; p->eCreate = 2; p->xStress = xStress; p->pStress = pStress; p->szCache = 100; @@ -44448,10 +43941,11 @@ sqlite3_pcache_page *pRes; assert( pCache!=0 ); assert( pCache->pCache!=0 ); assert( createFlag==3 || createFlag==0 ); + assert( pgno>0 ); assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) ); /* eCreate defines what to do if the page does not exist. ** 0 Do not allocate a new page. (createFlag==0) ** 1 Allocate a new page if doing so is inexpensive. @@ -44547,11 +44041,11 @@ assert( pPgHdr->pPage==0 ); memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty)); pPgHdr->pPage = pPage; pPgHdr->pData = pPage->pBuf; pPgHdr->pExtra = (void *)&pPgHdr[1]; - memset(pPgHdr->pExtra, 0, 8); + memset(pPgHdr->pExtra, 0, pCache->szExtra); pPgHdr->pCache = pCache; pPgHdr->pgno = pgno; pPgHdr->flags = PGHDR_CLEAN; return sqlite3PcacheFetchFinish(pCache,pgno,pPage); } @@ -46771,21 +46265,21 @@ #define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */ #ifdef SQLITE_OMIT_WAL # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalLimit(x,y) -# define sqlite3WalClose(v,w,x,y,z) 0 +# define sqlite3WalClose(w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalDbsize(y) 0 # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWriteTransaction(x) 0 # define sqlite3WalUndo(x,y,z) 0 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 -# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 +# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0 # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 # define sqlite3WalFramesize(z) 0 # define sqlite3WalFindFrame(x,y,z) 0 @@ -46799,11 +46293,11 @@ */ typedef struct Wal Wal; /* Open and close a connection to a write-ahead log. */ SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**); -SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *); +SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); /* Set the limiting size of a WAL file. */ SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64); /* Used by readers to open (lock) and close (unlock) a snapshot. A @@ -46842,11 +46336,10 @@ SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); /* Copy pages from the log to the database file */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Write-ahead log connection */ - sqlite3 *db, /* Check this handle's interrupt flag */ int eMode, /* One of PASSIVE, FULL and RESTART */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags to sync db file with (or 0) */ int nBuf, /* Size of buffer nBuf */ @@ -46874,11 +46367,10 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); #ifdef SQLITE_ENABLE_SNAPSHOT SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); -SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal); #endif #ifdef SQLITE_ENABLE_ZIPVFS /* If the WAL file is not empty, return the number of bytes of content ** stored in each frame (i.e. the db page-size when the WAL was created). @@ -47564,11 +47056,10 @@ int aStat[3]; /* Total cache hits, misses and writes */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ - int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */ #ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */ void (*xCodecFree)(void*); /* Destructor for the codec */ void *pCodec; /* First argument to xCodec... methods */ @@ -47685,24 +47176,18 @@ ** if( pPager->jfd->pMethods ){ ... */ #define isOpen(pFd) ((pFd)->pMethods!=0) /* -** Return true if this pager uses a write-ahead log to read page pgno. -** Return false if the pager reads pgno directly from the database. +** Return true if this pager uses a write-ahead log instead of the usual +** rollback journal. Otherwise false. */ -#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ) -SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){ - u32 iRead = 0; - int rc; - if( pPager->pWal==0 ) return 0; - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - return rc || iRead; -} -#endif #ifndef SQLITE_OMIT_WAL -# define pagerUseWal(x) ((x)->pWal!=0) +SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){ + return (pPager->pWal!=0); +} +# define pagerUseWal(x) sqlite3PagerUseWal(x) #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 # define pagerWalFrames(v,w,x,y) 0 # define pagerOpenWalIfPresent(z) SQLITE_OK @@ -47897,37 +47382,10 @@ return zRet; } #endif -/* Forward references to the various page getters */ -static int getPageNormal(Pager*,Pgno,DbPage**,int); -static int getPageError(Pager*,Pgno,DbPage**,int); -#if SQLITE_MAX_MMAP_SIZE>0 -static int getPageMMap(Pager*,Pgno,DbPage**,int); -#endif - -/* -** Set the Pager.xGet method for the appropriate routine used to fetch -** content from the pager. -*/ -static void setGetterMethod(Pager *pPager){ - if( pPager->errCode ){ - pPager->xGet = getPageError; -#if SQLITE_MAX_MMAP_SIZE>0 - }else if( USEFETCH(pPager) -#ifdef SQLITE_HAS_CODEC - && pPager->xCodec==0 -#endif - ){ - pPager->xGet = getPageMMap; -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - }else{ - pPager->xGet = getPageNormal; - } -} - /* ** Return true if it is necessary to write page *pPg into the sub-journal. ** A page needs to be written into the sub-journal if there exists one ** or more open savepoints for which: ** @@ -48738,11 +48196,10 @@ }else{ pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER); } if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); pPager->errCode = SQLITE_OK; - setGetterMethod(pPager); } pPager->journalOff = 0; pPager->journalHdr = 0; pPager->setMaster = 0; @@ -48776,11 +48233,10 @@ (pPager->errCode & 0xff)==SQLITE_IOERR ); if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); } return rc; } static int pager_truncate(Pager *pPager, Pgno nPage); @@ -48945,11 +48401,11 @@ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; pPager->nRec = 0; if( rc==SQLITE_OK ){ - if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){ + if( pagerFlushOnCommit(pPager, bCommit) ){ sqlite3PcacheCleanAll(pPager->pPCache); }else{ sqlite3PcacheClearWritable(pPager->pPCache); } sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); @@ -50344,11 +49800,10 @@ sqlite3_file *fd = pPager->fd; if( isOpen(fd) && fd->pMethods->iVersion>=3 ){ sqlite3_int64 sz; sz = pPager->szMmap; pPager->bUseFetch = (sz>0); - setGetterMethod(pPager); sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz); } #endif } @@ -50841,11 +50296,10 @@ rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr); } return rc; } -#if SQLITE_MAX_MMAP_SIZE>0 /* ** Obtain a reference to a memory mapped page object for page number pgno. ** The new object will use the pointer pData, obtained from xFetch(). ** If successful, set *ppPage to point to the new page reference ** and return SQLITE_OK. Otherwise, return an SQLite error code and set @@ -50864,12 +50318,11 @@ if( pPager->pMmapFreelist ){ *ppPage = p = pPager->pMmapFreelist; pPager->pMmapFreelist = p->pDirty; p->pDirty = 0; - assert( pPager->nExtra>=8 ); - memset(p->pExtra, 0, 8); + memset(p->pExtra, 0, pPager->nExtra); }else{ *ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra); if( p==0 ){ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData); return SQLITE_NOMEM_BKPT; @@ -50890,11 +50343,10 @@ p->pData = pData; pPager->nMmapOut++; return SQLITE_OK; } -#endif /* ** Release a reference to page pPg. pPg must have been returned by an ** earlier call to pagerAcquireMapPage(). */ @@ -50933,25 +50385,21 @@ ** This function always succeeds. If a transaction is active an attempt ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ -SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; - assert( db || pagerUseWal(pPager)==0 ); assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); pagerFreeMapHdrs(pPager); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL - assert( db || pPager->pWal==0 ); - sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize, - (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) - ); + sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp); pPager->pWal = 0; #endif pager_reset(pPager); if( MEMDB ){ pager_unlock(pPager); @@ -51466,13 +50914,11 @@ ** all information is held in cache. It is never written to disk. ** This can be used to implement an in-memory database. ** ** The nExtra parameter specifies the number of bytes of space allocated ** along with each page reference. This space is available to the user -** via the sqlite3PagerGetExtra() API. When a new page is allocated, the -** first 8 bytes of this space are zeroed but the remainder is uninitialized. -** (The extra space is used by btree as the MemPage object.) +** via the sqlite3PagerGetExtra() API. ** ** The flags argument is used to specify properties that affect the ** operation of the pager. It should be passed some bitwise combination ** of the PAGER_* flags. ** @@ -51698,12 +51144,12 @@ testcase( rc!=SQLITE_OK ); } /* Initialize the PCache object. */ if( rc==SQLITE_OK ){ + assert( nExtra<1000 ); nExtra = ROUND8(nExtra); - assert( nExtra>=8 && nExtra<1000 ); rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); } /* If an error occurred above, free the Pager structure and close the file. @@ -51764,11 +51210,10 @@ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ /* pPager->pBusyHandlerArg = 0; */ pPager->xReiniter = xReinit; - setGetterMethod(pPager); /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ /* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */ *ppPager = pPager; return SQLITE_OK; @@ -52178,21 +51623,14 @@ pagerUnlockAndRollback(pPager); } } /* -** The page getter methods each try to acquire a reference to a -** page with page number pgno. If the requested reference is +** Acquire a reference to page number pgno in pager pPager (a page +** reference has type DbPage*). If the requested reference is ** successfully obtained, it is copied to *ppPage and SQLITE_OK returned. ** -** There are different implementations of the getter method depending -** on the current state of the pager. -** -** getPageNormal() -- The normal getter -** getPageError() -- Used if the pager is in an error state -** getPageMmap() -- Used if memory-mapped I/O is enabled -** ** If the requested page is already in the cache, it is returned. ** Otherwise, a new page object is allocated and populated with data ** read from the database file. In some cases, the pcache module may ** choose not to allocate a new page object and may reuse an existing ** object with no outstanding references. @@ -52200,27 +51638,27 @@ ** The extra data appended to a page is always initialized to zeros the ** first time a page is loaded into memory. If the page requested is ** already in the cache when this function is called, then the extra ** data is left as it was when the page object was last used. ** -** If the database image is smaller than the requested page or if -** the flags parameter contains the PAGER_GET_NOCONTENT bit and the +** If the database image is smaller than the requested page or if a +** non-zero value is passed as the noContent parameter and the ** requested page is not already stored in the cache, then no ** actual disk read occurs. In this case the memory image of the ** page is initialized to all zeros. ** -** If PAGER_GET_NOCONTENT is true, it means that we do not care about -** the contents of the page. This occurs in two scenarios: +** If noContent is true, it means that we do not care about the contents +** of the page. This occurs in two scenarios: ** ** a) When reading a free-list leaf page from the database, and ** ** b) When a savepoint is being rolled back and we need to load ** a new page into the cache to be filled with the data read ** from the savepoint journal. ** -** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead -** of being read from the database. Additionally, the bits corresponding +** If noContent is true, then the data returned is zeroed instead of +** being read from the database. Additionally, the bits corresponding ** to pgno in Pager.pInJournal (bitvec of pages already written to the ** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open ** savepoints are set. This means if the page is made writable at any ** point in the future, using a call to sqlite3PagerWrite(), its contents ** will not be journaled. This saves IO. @@ -52234,64 +51672,130 @@ ** just returns 0. This routine acquires a read-lock the first time it ** has to go to disk, and could also playback an old journal if necessary. ** Since Lookup() never goes to disk, it never has to deal with locks ** or journal files. */ -static int getPageNormal( +SQLITE_PRIVATE int sqlite3PagerGet( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ int rc = SQLITE_OK; - PgHdr *pPg; - u8 noContent; /* True if PAGER_GET_NOCONTENT is set */ - sqlite3_pcache_page *pBase; + PgHdr *pPg = 0; + u32 iFrame = 0; /* Frame to read from WAL file */ + const int noContent = (flags & PAGER_GET_NOCONTENT); - assert( pPager->errCode==SQLITE_OK ); + /* It is acceptable to use a read-only (mmap) page for any page except + ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY + ** flag was specified by the caller. And so long as the db is not a + ** temporary or in-memory database. */ + const int bMmapOk = (pgno>1 && USEFETCH(pPager) + && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) +#ifdef SQLITE_HAS_CODEC + && pPager->xCodec==0 +#endif + ); + + /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here + ** allows the compiler optimizer to reuse the results of the "pgno>1" + ** test in the previous statement, and avoid testing pgno==0 in the + ** common case where pgno is large. */ + if( pgno<=1 && pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } assert( pPager->eState>=PAGER_READER ); assert( assert_pager_state(pPager) ); + assert( noContent==0 || bMmapOk==0 ); + assert( pPager->hasHeldSharedLock==1 ); - if( pgno==0 ) return SQLITE_CORRUPT_BKPT; - pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); - if( pBase==0 ){ + /* If the pager is in the error state, return an error immediately. + ** Otherwise, request the page from the PCache layer. */ + if( pPager->errCode!=SQLITE_OK ){ + rc = pPager->errCode; + }else{ + if( bMmapOk && pagerUseWal(pPager) ){ + rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); + if( rc!=SQLITE_OK ) goto pager_acquire_err; + } + + if( bMmapOk && iFrame==0 ){ + void *pData = 0; + + rc = sqlite3OsFetch(pPager->fd, + (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData + ); + + if( rc==SQLITE_OK && pData ){ + if( pPager->eState>PAGER_READER || pPager->tempFile ){ + pPg = sqlite3PagerLookup(pPager, pgno); + } + if( pPg==0 ){ + rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); + }else{ + sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); + } + if( pPg ){ + assert( rc==SQLITE_OK ); + *ppPage = pPg; + return SQLITE_OK; + } + } + if( rc!=SQLITE_OK ){ + goto pager_acquire_err; + } + } + + { + sqlite3_pcache_page *pBase; + pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); + if( pBase==0 ){ + rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); + if( rc!=SQLITE_OK ) goto pager_acquire_err; + if( pBase==0 ){ + pPg = *ppPage = 0; + rc = SQLITE_NOMEM_BKPT; + goto pager_acquire_err; + } + } + pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); + assert( pPg!=0 ); + } + } + + if( rc!=SQLITE_OK ){ + /* Either the call to sqlite3PcacheFetch() returned an error or the + ** pager was already in the error-state when this function was called. + ** Set pPg to 0 and jump to the exception handler. */ pPg = 0; - rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); - if( rc!=SQLITE_OK ) goto pager_acquire_err; - if( pBase==0 ){ - rc = SQLITE_NOMEM_BKPT; - goto pager_acquire_err; - } - } - pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase); + goto pager_acquire_err; + } assert( pPg==(*ppPage) ); assert( pPg->pgno==pgno ); assert( pPg->pPager==pPager || pPg->pPager==0 ); - noContent = (flags & PAGER_GET_NOCONTENT)!=0; if( pPg->pPager && !noContent ){ /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); pPager->aStat[PAGER_STAT_HIT]++; return SQLITE_OK; }else{ /* The pager cache has created a new page. Its content needs to - ** be initialized. But first some error checks: - ** - ** (1) The maximum page number is 2^31 - ** (2) Never try to fetch the locking page - */ + ** be initialized. */ + + pPg->pPager = pPager; + + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page + ** number greater than this, or the unused locking-page, is requested. */ if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } - pPg->pPager = pPager; - assert( !isOpen(pPager->fd) || !MEMDB ); if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){ rc = SQLITE_FULL; goto pager_acquire_err; @@ -52313,12 +51817,11 @@ sqlite3EndBenignMalloc(); } memset(pPg->pData, 0, pPager->pageSize); IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ - u32 iFrame = 0; /* Frame to read from WAL file */ - if( pagerUseWal(pPager) ){ + if( pagerUseWal(pPager) && bMmapOk==0 ){ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); if( rc!=SQLITE_OK ) goto pager_acquire_err; } assert( pPg->pPager==pPager ); pPager->aStat[PAGER_STAT_MISS]++; @@ -52327,119 +51830,22 @@ goto pager_acquire_err; } } pager_set_pagehash(pPg); } + return SQLITE_OK; pager_acquire_err: assert( rc!=SQLITE_OK ); if( pPg ){ sqlite3PcacheDrop(pPg); } pagerUnlockIfUnused(pPager); - *ppPage = 0; - return rc; -} - -#if SQLITE_MAX_MMAP_SIZE>0 -/* The page getter for when memory-mapped I/O is enabled */ -static int getPageMMap( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ - int rc = SQLITE_OK; - PgHdr *pPg = 0; - u32 iFrame = 0; /* Frame to read from WAL file */ - - /* It is acceptable to use a read-only (mmap) page for any page except - ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY - ** flag was specified by the caller. And so long as the db is not a - ** temporary or in-memory database. */ - const int bMmapOk = (pgno>1 - && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY)) - ); - - assert( USEFETCH(pPager) ); -#ifdef SQLITE_HAS_CODEC - assert( pPager->xCodec==0 ); -#endif - - /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here - ** allows the compiler optimizer to reuse the results of the "pgno>1" - ** test in the previous statement, and avoid testing pgno==0 in the - ** common case where pgno is large. */ - if( pgno<=1 && pgno==0 ){ - return SQLITE_CORRUPT_BKPT; - } - assert( pPager->eState>=PAGER_READER ); - assert( assert_pager_state(pPager) ); - assert( pPager->hasHeldSharedLock==1 ); - assert( pPager->errCode==SQLITE_OK ); - - if( bMmapOk && pagerUseWal(pPager) ){ - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame); - if( rc!=SQLITE_OK ){ - *ppPage = 0; - return rc; - } - } - if( bMmapOk && iFrame==0 ){ - void *pData = 0; - rc = sqlite3OsFetch(pPager->fd, - (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData - ); - if( rc==SQLITE_OK && pData ){ - if( pPager->eState>PAGER_READER || pPager->tempFile ){ - pPg = sqlite3PagerLookup(pPager, pgno); - } - if( pPg==0 ){ - rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ - sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); - } - if( pPg ){ - assert( rc==SQLITE_OK ); - *ppPage = pPg; - return SQLITE_OK; - } - } - if( rc!=SQLITE_OK ){ - *ppPage = 0; - return rc; - } - } - return getPageNormal(pPager, pgno, ppPage, flags); -} -#endif /* SQLITE_MAX_MMAP_SIZE>0 */ - -/* The page getter method for when the pager is an error state */ -static int getPageError( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ - UNUSED_PARAMETER(pgno); - UNUSED_PARAMETER(flags); - assert( pPager->errCode!=SQLITE_OK ); - *ppPage = 0; - return pPager->errCode; -} - - -/* Dispatch all page fetch requests to the appropriate getter method. -*/ -SQLITE_PRIVATE int sqlite3PagerGet( - Pager *pPager, /* The pager open on the database file */ - Pgno pgno, /* Page number to fetch */ - DbPage **ppPage, /* Write a pointer to the page here */ - int flags /* PAGER_GET_XXX flags */ -){ - return pPager->xGet(pPager, pgno, ppPage, flags); + + *ppPage = 0; + return rc; } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, @@ -52911,15 +52317,15 @@ SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); - if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ + if( pPager->errCode ){ + return pPager->errCode; + }else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); return SQLITE_OK; - }else if( pPager->errCode ){ - return pPager->errCode; }else if( pPager->sectorSize > (u32)pPager->pageSize ){ assert( pPager->tempFile==0 ); return pagerWriteLargeSector(pPg); }else{ return pager_write(pPg); @@ -53410,11 +52816,10 @@ ** state to indicate that the contents of the cache may not be trusted. ** Any active readers will get SQLITE_ABORT. */ pPager->errCode = SQLITE_ABORT; pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); return rc; } }else{ rc = pager_playback(pPager, 0); } @@ -53672,11 +53077,10 @@ pPager->journalMode==PAGER_JOURNALMODE_OFF && pPager->eState>=PAGER_WRITER_CACHEMOD ){ pPager->errCode = SQLITE_ABORT; pPager->eState = PAGER_ERROR; - setGetterMethod(pPager); } #endif } return rc; @@ -53745,11 +53149,10 @@ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); pPager->xCodec = pPager->memDb ? 0 : xCodec; pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree; pPager->pCodec = pCodec; - setGetterMethod(pPager); pagerReportSize(pPager); } SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){ return pPager->pCodec; } @@ -54155,20 +53558,14 @@ ** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint() ** or wal_blocking_checkpoint() API functions. ** ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. */ -SQLITE_PRIVATE int sqlite3PagerCheckpoint( - Pager *pPager, /* Checkpoint on this pager */ - sqlite3 *db, /* Db handle used to check for interrupts */ - int eMode, /* Type of checkpoint */ - int *pnLog, /* OUT: Final number of frames in log */ - int *pnCkpt /* OUT: Final number of checkpointed frames */ -){ +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){ int rc = SQLITE_OK; if( pPager->pWal ){ - rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, + rc = sqlite3WalCheckpoint(pPager->pWal, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), pPager->pBusyHandlerArg, pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); @@ -54296,11 +53693,11 @@ ** Before closing the log file, this function attempts to take an ** EXCLUSIVE lock on the database file. If this cannot be obtained, an ** error (SQLITE_BUSY) is returned and the log connection is not closed. ** If successful, the EXCLUSIVE lock is not released before returning. */ -SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ int rc = SQLITE_OK; assert( pPager->journalMode==PAGER_JOURNALMODE_WAL ); /* If the log file is not already open, but does exist in the file-system, @@ -54324,11 +53721,11 @@ ** the database file, the log and log-summary files will be deleted. */ if( rc==SQLITE_OK && pPager->pWal ){ rc = pagerExclusiveLock(pPager); if( rc==SQLITE_OK ){ - rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, + rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, (u8*)pPager->pTmpSpace); pPager->pWal = 0; pagerFixMaplimit(pPager); if( rc && !pPager->exclusiveMode ) pagerUnlockDb(pPager, SHARED_LOCK); } @@ -54357,24 +53754,10 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){ int rc = SQLITE_OK; if( pPager->pWal ){ sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); }else{ - rc = SQLITE_ERROR; - } - return rc; -} - -/* -** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this -** is not a WAL database, return an error. -*/ -SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){ - int rc; - if( pPager->pWal ){ - rc = sqlite3WalSnapshotRecover(pPager->pWal); - }else{ rc = SQLITE_ERROR; } return rc; } #endif /* SQLITE_ENABLE_SNAPSHOT */ @@ -56121,11 +55504,10 @@ ** checkpoint is running (in any other thread or process) at the same ** time. */ static int walCheckpoint( Wal *pWal, /* Wal connection */ - sqlite3 *db, /* Check for interrupts on this handle */ int eMode, /* One of PASSIVE, FULL or RESTART */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags for OsSync() (or 0) */ u8 *zBuf /* Temporary buffer to use */ @@ -56216,14 +55598,10 @@ /* Iterate through the contents of the WAL, copying data to the db file */ while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); - if( db->u1.isInterrupted ){ - rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; - break; - } if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){ continue; } iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE; /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */ @@ -56324,11 +55702,10 @@ /* ** Close a connection to a log file. */ SQLITE_PRIVATE int sqlite3WalClose( Wal *pWal, /* Wal to close */ - sqlite3 *db, /* For interrupt flag */ int sync_flags, /* Flags to pass to OsSync() (or 0) */ int nBuf, u8 *zBuf /* Buffer of at least nBuf bytes */ ){ int rc = SQLITE_OK; @@ -56341,18 +55718,17 @@ ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ - if( zBuf!=0 - && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE)) - ){ + rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); + if( rc==SQLITE_OK ){ if( pWal->exclusiveMode==WAL_NORMAL_MODE ){ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE; } - rc = sqlite3WalCheckpoint(pWal, db, - SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 + rc = sqlite3WalCheckpoint( + pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0 ); if( rc==SQLITE_OK ){ int bPersist = -1; sqlite3OsFileControlHint( pWal->pDbFd, SQLITE_FCNTL_PERSIST_WAL, &bPersist @@ -56777,88 +56153,10 @@ pWal->readLock = (i16)mxI; } return rc; } -#ifdef SQLITE_ENABLE_SNAPSHOT -/* -** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted -** variable so that older snapshots can be accessed. To do this, loop -** through all wal frames from nBackfillAttempted to (nBackfill+1), -** comparing their content to the corresponding page with the database -** file, if any. Set nBackfillAttempted to the frame number of the -** first frame for which the wal file content matches the db file. -** -** This is only really safe if the file-system is such that any page -** writes made by earlier checkpointers were atomic operations, which -** is not always true. It is also possible that nBackfillAttempted -** may be left set to a value larger than expected, if a wal frame -** contains content that duplicate of an earlier version of the same -** page. -** -** SQLITE_OK is returned if successful, or an SQLite error code if an -** error occurs. It is not an error if nBackfillAttempted cannot be -** decreased at all. -*/ -SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){ - int rc; - - assert( pWal->readLock>=0 ); - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int szPage = (int)pWal->szPage; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(szPage); - void *pBuf2 = sqlite3_malloc(szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){ - volatile ht_slot *dummy; - volatile u32 *aPgno; /* Array of page numbers */ - u32 iZero; /* Frame corresponding to aPgno[0] */ - u32 pgno; /* Page number in db file */ - i64 iDbOff; /* Offset of db file entry */ - i64 iWalOff; /* Offset of wal file entry */ - - rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero); - if( rc!=SQLITE_OK ) break; - pgno = aPgno[i-iZero]; - iDbOff = (i64)(pgno-1) * szPage; - - if( iDbOff+szPage<=szDb ){ - iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; - rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); - - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); - } - - if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ - break; - } - } - - pInfo->nBackfillAttempted = i-1; - } - } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); - } - walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); - } - - return rc; -} -#endif /* SQLITE_ENABLE_SNAPSHOT */ - /* ** Begin a read transaction on the database. ** ** This routine used to be called sqlite3OpenSnapshot() and with good reason: ** it takes a snapshot of the state of the WAL and wal-index for the current @@ -56917,15 +56215,11 @@ ** checkpointer has already determined that it will checkpoint ** snapshot X, where X is later in the wal file than pSnapshot, but ** has not yet set the pInfo->nBackfillAttempted variable to indicate ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock - ** before checking pInfo->nBackfillAttempted. - ** - ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing - ** this already? - */ + ** before checking pInfo->nBackfillAttempted. */ rc = walLockShared(pWal, WAL_CKPT_LOCK); if( rc==SQLITE_OK ){ /* Check that the wal file has not been wrapped. Assuming that it has ** not, also check that no checkpointer has attempted to checkpoint any @@ -57678,11 +56972,10 @@ ** If parameter xBusy is not NULL, it is a pointer to a busy-handler ** callback. In this case this function runs a blocking checkpoint. */ SQLITE_PRIVATE int sqlite3WalCheckpoint( Wal *pWal, /* Wal connection */ - sqlite3 *db, /* Check this handle's interrupt flag */ int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */ int (*xBusy)(void*), /* Function to call when busy */ void *pBusyArg, /* Context argument for xBusyHandler */ int sync_flags, /* Flags to sync db file with (or 0) */ int nBuf, /* Size of temporary buffer */ @@ -57753,11 +57046,11 @@ if( rc==SQLITE_OK ){ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); } /* If no error occurred, set the output variables. */ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; @@ -57873,18 +57166,13 @@ ** in the object. */ SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ int rc = SQLITE_OK; WalIndexHdr *pRet; - static const u32 aZero[4] = { 0, 0, 0, 0 }; assert( pWal->readLock>=0 && pWal->writeLock==0 ); - if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){ - *ppSnapshot = 0; - return SQLITE_ERROR; - } pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr)); if( pRet==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr)); @@ -58218,53 +57506,59 @@ #define PTF_ZERODATA 0x02 #define PTF_LEAFDATA 0x04 #define PTF_LEAF 0x08 /* -** An instance of this object stores information about each a single database -** page that has been loaded into memory. The information in this object -** is derived from the raw on-disk page content. +** As each page of the file is loaded into memory, an instance of the following +** structure is appended and initialized to zero. This structure stores +** information about the page that is decoded from the raw file page. ** -** As each database page is loaded into memory, the pager allocats an -** instance of this object and zeros the first 8 bytes. (This is the -** "extra" information associated with each page of the pager.) +** The pParent field points back to the parent page. This allows us to +** walk up the BTree from any leaf to the root. Care must be taken to +** unref() the parent page pointer when this page is no longer referenced. +** The pageDestructor() routine handles that chore. ** ** Access to all fields of this structure is controlled by the mutex ** stored in MemPage.pBt->mutex. */ struct MemPage { u8 isInit; /* True if previously initialized. MUST BE FIRST! */ - u8 bBusy; /* Prevent endless loops on corrupt database files */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ u8 intKey; /* True if table b-trees. False for index b-trees */ u8 intKeyLeaf; /* True if the leaf of an intKey table */ - Pgno pgno; /* Page number for this page */ - /* Only the first 8 bytes (above) are zeroed by pager.c when a new page - ** is allocated. All fields that follow must be initialized before use */ u8 leaf; /* True if a leaf page */ u8 hdrOffset; /* 100 for page 1. 0 otherwise */ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ u8 max1bytePayload; /* min(maxLocal,127) */ - u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 bBusy; /* Prevent endless loops on corrupt database files */ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ u16 maskPage; /* Mask for page offset */ - u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th + u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th ** non-overflow cell */ - u8 *apOvfl[4]; /* Pointers to the body of overflow cells */ + u8 *apOvfl[5]; /* Pointers to the body of overflow cells */ BtShared *pBt; /* Pointer to BtShared that this page is part of */ u8 *aData; /* Pointer to disk image of the page data */ u8 *aDataEnd; /* One byte past the end of usable data */ u8 *aCellIdx; /* The cell index area */ u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */ DbPage *pDbPage; /* Pager page handle */ u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */ void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */ + Pgno pgno; /* Page number for this page */ }; +/* +** The in-memory image of a disk page has the auxiliary information appended +** to the end. EXTRA_SIZE is the number of bytes of space needed to hold +** that extra information. +*/ +#define EXTRA_SIZE sizeof(MemPage) + /* ** A linked list of the following structures is stored at BtShared.pLock. ** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor ** is opened on the table with root page BtShared.iTable. Locks are removed ** from this list when a transaction is committed or rolled back, or when @@ -58651,13 +57945,15 @@ ** two-byte aligned address. get2bytea() is only used for accessing the ** cell addresses in a btree header. */ #if SQLITE_BYTEORDER==4321 # define get2byteAligned(x) (*(u16*)(x)) -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && GCC_VERSION>=4008000 # define get2byteAligned(x) __builtin_bswap16(*(u16*)(x)) -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 +#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \ + && defined(_MSC_VER) && _MSC_VER>=1300 # define get2byteAligned(x) _byteswap_ushort(*(u16*)(x)) #else # define get2byteAligned(x) ((x)[0]<<8 | (x)[1]) #endif @@ -58828,39 +58124,28 @@ ** Enter the mutexes in accending order by BtShared pointer address ** to avoid the possibility of deadlock when two threads with ** two or more btrees in common both try to lock all their btrees ** at the same instant. */ -static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ int i; - int skipOk = 1; Btree *p; assert( sqlite3_mutex_held(db->mutex) ); for(i=0; inDb; i++){ p = db->aDb[i].pBt; - if( p && p->sharable ){ - sqlite3BtreeEnter(p); - skipOk = 0; - } - } - db->skipBtreeMutex = skipOk; -} -SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){ - if( db->skipBtreeMutex==0 ) btreeEnterAll(db); -} -static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ + if( p ) sqlite3BtreeEnter(p); + } +} +SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ int i; Btree *p; assert( sqlite3_mutex_held(db->mutex) ); for(i=0; inDb; i++){ p = db->aDb[i].pBt; if( p ) sqlite3BtreeLeave(p); } } -SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){ - if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); -} #ifndef NDEBUG /* ** Return true if the current thread holds the database connection ** mutex and all required BtShared mutexes. @@ -59588,11 +58873,11 @@ /* For an index btree, save the complete key content */ void *pKey; pCur->nKey = sqlite3BtreePayloadSize(pCur); pKey = sqlite3Malloc( pCur->nKey ); if( pKey ){ - rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey); + rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); if( rc==SQLITE_OK ){ pCur->pKey = pKey; }else{ sqlite3_free(pKey); } @@ -59719,27 +59004,30 @@ int bias, /* Bias search to the high end */ int *pRes /* Write search results here */ ){ int rc; /* Status code */ UnpackedRecord *pIdxKey; /* Unpacked index key */ + char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */ + char *pFree = 0; if( pKey ){ assert( nKey==(i64)(int)nKey ); - pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo); + pIdxKey = sqlite3VdbeAllocUnpackedRecord( + pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree + ); if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 ){ - rc = SQLITE_CORRUPT_BKPT; - goto moveto_done; + sqlite3DbFree(pCur->pKeyInfo->db, pFree); + return SQLITE_CORRUPT_BKPT; } }else{ pIdxKey = 0; } rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes); -moveto_done: - if( pIdxKey ){ - sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey); + if( pFree ){ + sqlite3DbFree(pCur->pKeyInfo->db, pFree); } return rc; } /* @@ -60273,22 +59561,21 @@ } #endif /* -** Defragment the page given. This routine reorganizes cells within the -** page so that there are no free-blocks on the free-block list. -** -** Parameter nMaxFrag is the maximum amount of fragmented space that may be -** present in the page after this routine returns. +** Defragment the page given. All Cells are moved to the +** end of the page and all free space is collected into one +** big FreeBlk that occurs in between the header and cell +** pointer array and the cell content area. ** ** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a ** b-tree page so that there are no freeblocks or fragment bytes, all ** unused bytes are contained in the unallocated space region, and all ** cells are packed tightly at the end of the page. */ -static int defragmentPage(MemPage *pPage, int nMaxFrag){ +static int defragmentPage(MemPage *pPage){ int i; /* Loop counter */ int pc; /* Address of the i-th cell */ int hdr; /* Offset to the page header */ int size; /* Size of a cell */ int usableSize; /* Number of usable bytes on a page */ @@ -60298,10 +59585,11 @@ unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ unsigned char *src; /* Source of content */ int iCellFirst; /* First allowable cell index */ int iCellLast; /* Last possible cell index */ + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); @@ -60310,60 +59598,13 @@ src = data = pPage->aData; hdr = pPage->hdrOffset; cellOffset = pPage->cellOffset; nCell = pPage->nCell; assert( nCell==get2byte(&data[hdr+3]) ); - iCellFirst = cellOffset + 2*nCell; usableSize = pPage->pBt->usableSize; - - /* This block handles pages with two or fewer free blocks and nMaxFrag - ** or fewer fragmented bytes. In this case it is faster to move the - ** two (or one) blocks of cells using memmove() and add the required - ** offsets to each pointer in the cell-pointer array than it is to - ** reconstruct the entire page. */ - if( (int)data[hdr+7]<=nMaxFrag ){ - int iFree = get2byte(&data[hdr+1]); - if( iFree ){ - int iFree2 = get2byte(&data[iFree]); - - /* pageFindSlot() has already verified that free blocks are sorted - ** in order of offset within the page, and that no block extends - ** past the end of the page. Provided the two free slots do not - ** overlap, this guarantees that the memmove() calls below will not - ** overwrite the usableSize byte buffer, even if the database page - ** is corrupt. */ - assert( iFree2==0 || iFree2>iFree ); - assert( iFree+get2byte(&data[iFree+2]) <= usableSize ); - assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize ); - - if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){ - u8 *pEnd = &data[cellOffset + nCell*2]; - u8 *pAddr; - int sz2 = 0; - int sz = get2byte(&data[iFree+2]); - int top = get2byte(&data[hdr+5]); - if( iFree2 ){ - if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT; - sz2 = get2byte(&data[iFree2+2]); - assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); - memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); - sz += sz2; - } - cbrk = top+sz; - assert( cbrk+(iFree-top) <= usableSize ); - memmove(&data[cbrk], &data[top], iFree-top); - for(pAddr=&data[cellOffset]; pAddrnFree ){ - return SQLITE_CORRUPT_BKPT; - } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); data[hdr+1] = 0; data[hdr+2] = 0; + data[hdr+7] = 0; memset(&data[iCellFirst], 0, cbrk-iCellFirst); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + if( cbrk-iCellFirst!=pPage->nFree ){ + return SQLITE_CORRUPT_BKPT; + } return SQLITE_OK; } /* ** Search the free-list on page pPg for space to store a cell nByte bytes in @@ -60542,14 +59781,14 @@ ** to see if defragmentation is necessary. */ testcase( gap+2+nByte==top ); if( gap+2+nByte>top ){ assert( pPage->nCell>0 || CORRUPT_DB ); - rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte))); + rc = defragmentPage(pPage); if( rc ) return rc; top = get2byteNotZero(&data[hdr+5]); - assert( gap+2+nByte<=top ); + assert( gap+nByte<=top ); } /* Allocate memory from the gap in between the cell pointer array ** and the cell content area. The btreeInitPage() call has already @@ -60745,11 +59984,11 @@ assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); if( !pPage->isInit ){ - int pc; /* Address of a freeblock within pPage->aData[] */ + u16 pc; /* Address of a freeblock within pPage->aData[] */ u8 hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ BtShared *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ u16 cellOffset; /* Offset from start of page to first cell pointer */ @@ -60825,13 +60064,22 @@ ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the ** start of the first freeblock on the page, or is zero if there are no ** freeblocks. */ pc = get2byte(&data[hdr+1]); nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */ - if( pc>0 ){ - u32 next, size; - if( pc0 ){ + u16 next, size; + if( pciCellLast ){ /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will ** always be at least one cell before the first freeblock. + ** + ** Or, the freeblock is off the end of the page */ return SQLITE_CORRUPT_BKPT; } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){ + /* Free blocks must be in ascending order. And the last byte of + ** the free-block must lie on the database page. */ + return SQLITE_CORRUPT_BKPT; + } @@ -60838,21 +60086,7 @@ - while( 1 ){ - if( pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */ - } - next = get2byte(&data[pc]); - size = get2byte(&data[pc+2]); - nFree = nFree + size; - if( next<=pc+size+3 ) break; - pc = next; - } - if( next>0 ){ - return SQLITE_CORRUPT_BKPT; /* Freeblock not in ascending order */ - } - if( pc+size>(unsigned int)usableSize ){ - return SQLITE_CORRUPT_BKPT; /* Last freeblock extends past page end */ - } + nFree = nFree + size; + pc = next; } /* At this point, nFree contains the sum of the offset to the start ** of the cell-content area plus the number of free bytes within ** the cell-content area. If this is greater than the usable-size @@ -61289,11 +60523,11 @@ if( pBt==0 ){ rc = SQLITE_NOMEM_BKPT; goto btree_open_out; } rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, - sizeof(MemPage), flags, vfsFlags, pageReinit); + EXTRA_SIZE, flags, vfsFlags, pageReinit); if( rc==SQLITE_OK ){ sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap); rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); } if( rc!=SQLITE_OK ){ @@ -61402,30 +60636,23 @@ *ppBtree = p; btree_open_out: if( rc!=SQLITE_OK ){ if( pBt && pBt->pPager ){ - sqlite3PagerClose(pBt->pPager, 0); + sqlite3PagerClose(pBt->pPager); } sqlite3_free(pBt); sqlite3_free(p); *ppBtree = 0; }else{ - sqlite3_file *pFile; - /* If the B-Tree was successfully opened, set the pager-cache size to the ** default value. Except, when opening on an existing shared pager-cache, ** do not change the pager-cache size. */ if( sqlite3BtreeSchema(p, 0, 0)==0 ){ sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE); } - - pFile = sqlite3PagerFile(pBt->pPager); - if( pFile->pMethods ){ - sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db); - } } if( mutexOpen ){ assert( sqlite3_mutex_held(mutexOpen) ); sqlite3_mutex_leave(mutexOpen); } @@ -61551,11 +60778,11 @@ ** it without having to hold the mutex. ** ** Clean out and delete the BtShared object. */ assert( !pBt->pCursor ); - sqlite3PagerClose(pBt->pPager, p->db); + sqlite3PagerClose(pBt->pPager); if( pBt->xFreeSchema && pBt->pSchema ){ pBt->xFreeSchema(pBt->pSchema); } sqlite3DbFree(0, pBt->pSchema); freeTempSpace(pBt); @@ -61817,35 +61044,10 @@ sqlite3BtreeLeave(p); return rc; #endif } -/* -** If the user has not set the safety-level for this database connection -** using "PRAGMA synchronous", and if the safety-level is not already -** set to the value passed to this function as the second parameter, -** set it so. -*/ -#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS -static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){ - sqlite3 *db; - Db *pDb; - if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){ - while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; } - if( pDb->bSyncSet==0 - && pDb->safety_level!=safety_level - && pDb!=&db->aDb[1] - ){ - pDb->safety_level = safety_level; - sqlite3PagerSetFlags(pBt->pPager, - pDb->safety_level | (db->flags & PAGER_FLAGS_MASK)); - } - } -} -#else -# define setDefaultSyncFlag(pBt,safety_level) -#endif /* ** Get a reference to pPage1 of the database file. This will ** also acquire a readlock on that file. ** @@ -61915,19 +61117,30 @@ int isOpen = 0; rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen); if( rc!=SQLITE_OK ){ goto page1_init_failed; }else{ - setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1); +#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS + sqlite3 *db; + Db *pDb; + if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){ + while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; } + if( pDb->bSyncSet==0 + && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1 + ){ + pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1; + sqlite3PagerSetFlags(pBt->pPager, + pDb->safety_level | (db->flags & PAGER_FLAGS_MASK)); + } + } +#endif if( isOpen==0 ){ releasePage(pPage1); return SQLITE_OK; } } rc = SQLITE_NOTADB; - }else{ - setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1); } #endif /* EVIDENCE-OF: R-15465-20813 The maximum and minimum embedded payload ** fractions and the leaf payload fraction values must be 64, 32, and 32. @@ -62312,15 +61525,18 @@ static int setChildPtrmaps(MemPage *pPage){ int i; /* Counter variable */ int nCell; /* Number of cells in page pPage */ int rc; /* Return code */ BtShared *pBt = pPage->pBt; + u8 isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); rc = btreeInitPage(pPage); - if( rc!=SQLITE_OK ) return rc; + if( rc!=SQLITE_OK ){ + goto set_child_ptrmaps_out; + } nCell = pPage->nCell; for(i=0; ileaf ){ Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno, &rc); } +set_child_ptrmaps_out: + pPage->isInit = isInitOrig; return rc; } /* ** Somewhere on pPage is a pointer to page iFrom. Modify this pointer so @@ -62362,10 +61580,11 @@ if( get4byte(pPage->aData)!=iFrom ){ return SQLITE_CORRUPT_BKPT; } put4byte(pPage->aData, iTo); }else{ + u8 isInitOrig = pPage->isInit; int i; int nCell; int rc; rc = btreeInitPage(pPage); @@ -62375,18 +61594,16 @@ for(i=0; ixParseCell(pPage, pCell, &info); - if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_BKPT; - } - if( iFrom==get4byte(pCell+info.nSize-4) ){ - put4byte(pCell+info.nSize-4, iTo); - break; - } + if( info.nLocalaData+pPage->maskPage + && iFrom==get4byte(pCell+info.nSize-4) + ){ + put4byte(pCell+info.nSize-4, iTo); + break; } }else{ if( get4byte(pCell)==iFrom ){ put4byte(pCell, iTo); break; @@ -62399,10 +61616,12 @@ get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ return SQLITE_CORRUPT_BKPT; } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } + + pPage->isInit = isInitOrig; } return SQLITE_OK; } @@ -63057,16 +62276,11 @@ if( p && p->inTrans==TRANS_WRITE ){ BtShared *pBt = p->pBt; assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) ); sqlite3BtreeEnter(p); - if( op==SAVEPOINT_ROLLBACK ){ - rc = saveAllCursors(pBt, 0, 0); - } - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint); - } + rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint); if( rc==SQLITE_OK ){ if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){ pBt->nPage = 0; } rc = newDatabase(pBt); @@ -63298,14 +62512,10 @@ */ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){ return pCur && pCur->eState==CURSOR_VALID; } #endif /* NDEBUG */ -SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){ - assert( pCur!=0 ); - return pCur->eState==CURSOR_VALID; -} /* ** Return the value of the integer key or "rowid" for a table btree. ** This routine is only valid for a cursor that is pointing into a ** ordinary table btree. If the cursor points to an index btree or @@ -63448,24 +62658,25 @@ ** for the entry that the pCur cursor is pointing to. The eOp ** argument is interpreted as follows: ** ** 0: The operation is a read. Populate the overflow cache. ** 1: The operation is a write. Populate the overflow cache. +** 2: The operation is a read. Do not populate the overflow cache. ** ** A total of "amt" bytes are read or written beginning at "offset". ** Data is read to or from the buffer pBuf. ** ** The content being read or written might appear on the main page ** or be scattered out on multiple overflow pages. ** -** If the current cursor entry uses one or more overflow pages -** this function may allocate space for and lazily populate -** the overflow page-list cache array (BtCursor.aOverflow). +** If the current cursor entry uses one or more overflow pages and the +** eOp argument is not 2, this function may allocate space for and lazily +** populates the overflow page-list cache array (BtCursor.aOverflow). ** Subsequent calls use this cache to make seeking to the supplied offset ** more efficient. ** -** Once an overflow page-list cache has been allocated, it must be +** Once an overflow page-list cache has been allocated, it may be ** invalidated if some other cursor writes to the same table, or if ** the cursor is moved to a different row. Additionally, in auto-vacuum ** mode, the following events may invalidate an overflow page-list cache. ** ** * An incremental vacuum, @@ -63483,21 +62694,25 @@ int rc = SQLITE_OK; int iIdx = 0; MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ #ifdef SQLITE_DIRECT_OVERFLOW_READ - unsigned char * const pBufStart = pBuf; /* Start of original out buffer */ + unsigned char * const pBufStart = pBuf; + int bEnd; /* True if reading to end of data */ #endif assert( pPage ); - assert( eOp==0 || eOp==1 ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->aiIdx[pCur->iPage]nCell ); assert( cursorHoldsMutex(pCur) ); + assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */ getCellInfo(pCur); aPayload = pCur->info.pPayload; +#ifdef SQLITE_DIRECT_OVERFLOW_READ + bEnd = offset+amt==pCur->info.nPayload; +#endif assert( offset+amt <= pCur->info.nPayload ); assert( aPayload > pPage->aData ); if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){ /* Trying to read or write past the end of the data is an error. The @@ -63512,11 +62727,11 @@ if( offsetinfo.nLocal ){ int a = amt; if( a+offset>pCur->info.nLocal ){ a = pCur->info.nLocal - offset; } - rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); + rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage); offset = 0; pBuf += a; amt -= a; }else{ offset -= pCur->info.nLocal; @@ -63528,58 +62743,69 @@ Pgno nextPage; nextPage = get4byte(&aPayload[pCur->info.nLocal]); /* If the BtCursor.aOverflow[] has not been allocated, allocate it now. + ** Except, do not allocate aOverflow[] for eOp==2. ** ** The aOverflow[] array is sized at one entry for each overflow page ** in the overflow chain. The page number of the first overflow page is ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array ** means "not yet known" (the cache is lazily populated). */ - if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){ + if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; if( nOvfl>pCur->nOvflAlloc ){ Pgno *aNew = (Pgno*)sqlite3Realloc( pCur->aOverflow, nOvfl*2*sizeof(Pgno) ); if( aNew==0 ){ - return SQLITE_NOMEM_BKPT; + rc = SQLITE_NOMEM_BKPT; }else{ pCur->nOvflAlloc = nOvfl*2; pCur->aOverflow = aNew; } } - memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); - pCur->curFlags |= BTCF_ValidOvfl; - }else{ - /* If the overflow page-list cache has been allocated and the - ** entry for the first required overflow page is valid, skip - ** directly to it. - */ - if( pCur->aOverflow[offset/ovflSize] ){ - iIdx = (offset/ovflSize); - nextPage = pCur->aOverflow[iIdx]; - offset = (offset%ovflSize); + if( rc==SQLITE_OK ){ + memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno)); + pCur->curFlags |= BTCF_ValidOvfl; } } - assert( rc==SQLITE_OK && amt>0 ); - while( nextPage ){ + /* If the overflow page-list cache has been allocated and the + ** entry for the first required overflow page is valid, skip + ** directly to it. + */ + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 + && pCur->aOverflow[offset/ovflSize] + ){ + iIdx = (offset/ovflSize); + nextPage = pCur->aOverflow[iIdx]; + offset = (offset%ovflSize); + } + + for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ + /* If required, populate the overflow page-list cache. */ - assert( pCur->aOverflow[iIdx]==0 - || pCur->aOverflow[iIdx]==nextPage - || CORRUPT_DB ); - pCur->aOverflow[iIdx] = nextPage; + if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){ + assert( pCur->aOverflow[iIdx]==0 + || pCur->aOverflow[iIdx]==nextPage + || CORRUPT_DB ); + pCur->aOverflow[iIdx] = nextPage; + } if( offset>=ovflSize ){ /* The only reason to read this page is to obtain the page ** number for the next page in the overflow chain. The page ** data is not required. So first try to lookup the overflow ** page-list cache, if any, then fall back to the getOverflowPage() ** function. + ** + ** Note that the aOverflow[] array must be allocated because eOp!=2 + ** here. If eOp==2, then offset==0 and this branch is never taken. */ + assert( eOp!=2 ); assert( pCur->curFlags & BTCF_ValidOvfl ); assert( pCur->pBtree->db==pBt->db ); if( pCur->aOverflow[iIdx+1] ){ nextPage = pCur->aOverflow[iIdx+1]; }else{ @@ -63589,11 +62815,11 @@ }else{ /* Need to read this page properly. It contains some of the ** range of data that is being read (eOp==0) or written (eOp!=0). */ #ifdef SQLITE_DIRECT_OVERFLOW_READ - sqlite3_file *fd; /* File from which to do direct overflow read */ + sqlite3_file *fd; #endif int a = amt; if( a + offset > ovflSize ){ a = ovflSize - offset; } @@ -63601,29 +62827,31 @@ #ifdef SQLITE_DIRECT_OVERFLOW_READ /* If all the following are true: ** ** 1) this is a read operation, and ** 2) data is required from the start of this overflow page, and - ** 3) there is no open write-transaction, and - ** 4) the database is file-backed, and - ** 5) the page is not in the WAL file - ** 6) at least 4 bytes have already been read into the output buffer + ** 3) the database is file-backed, and + ** 4) there is no open write-transaction, and + ** 5) the database is not a WAL database, + ** 6) all data from the page is being read. + ** 7) at least 4 bytes have already been read into the output buffer ** ** then data can be read directly from the database file into the ** output buffer, bypassing the page-cache altogether. This speeds ** up loading large records that span many overflow pages. */ - if( eOp==0 /* (1) */ + if( (eOp&0x01)==0 /* (1) */ && offset==0 /* (2) */ - && pBt->inTransaction==TRANS_READ /* (3) */ - && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */ - && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */ - && &pBuf[-4]>=pBufStart /* (6) */ + && (bEnd || a==ovflSize) /* (6) */ + && pBt->inTransaction==TRANS_READ /* (4) */ + && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */ + && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */ + && &pBuf[-4]>=pBufStart /* (7) */ ){ u8 aSave[4]; u8 *aWrite = &pBuf[-4]; - assert( aWrite>=pBufStart ); /* due to (6) */ + assert( aWrite>=pBufStart ); /* hence (7) */ memcpy(aSave, aWrite, 4); rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); nextPage = get4byte(aWrite); memcpy(aWrite, aSave, 4); }else @@ -63630,89 +62858,80 @@ #endif { DbPage *pDbPage; rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage, - (eOp==0 ? PAGER_GET_READONLY : 0) + ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0) ); if( rc==SQLITE_OK ){ aPayload = sqlite3PagerGetData(pDbPage); nextPage = get4byte(aPayload); - rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); + rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage); sqlite3PagerUnref(pDbPage); offset = 0; } } amt -= a; - if( amt==0 ) return rc; pBuf += a; } - if( rc ) break; - iIdx++; } } if( rc==SQLITE_OK && amt>0 ){ - return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */ + return SQLITE_CORRUPT_BKPT; } return rc; } /* -** Read part of the payload for the row at which that cursor pCur is currently -** pointing. "amt" bytes will be transferred into pBuf[]. The transfer +** Read part of the key associated with cursor pCur. Exactly +** "amt" bytes will be transferred into pBuf[]. The transfer ** begins at "offset". ** -** pCur can be pointing to either a table or an index b-tree. -** If pointing to a table btree, then the content section is read. If -** pCur is pointing to an index b-tree then the key section is read. -** -** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing -** to a valid row in the table. For sqlite3BtreePayloadChecked(), the -** cursor might be invalid or might need to be restored before being read. +** The caller must ensure that pCur is pointing to a valid row +** in the table. ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ -SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0); } /* -** This variant of sqlite3BtreePayload() works even if the cursor has not -** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read() -** interface. +** Read part of the data associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. */ +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; + #ifndef SQLITE_OMIT_INCRBLOB -static SQLITE_NOINLINE int accessPayloadChecked( - BtCursor *pCur, - u32 offset, - u32 amt, - void *pBuf -){ - int rc; if ( pCur->eState==CURSOR_INVALID ){ return SQLITE_ABORT; } - assert( cursorOwnsBtShared(pCur) ); - rc = btreeRestoreCursorPosition(pCur); - return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0); -} -SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ - if( pCur->eState==CURSOR_VALID ){ - assert( cursorOwnsBtShared(pCur) ); - return accessPayload(pCur, offset, amt, pBuf, 0); - }else{ - return accessPayloadChecked(pCur, offset, amt, pBuf); - } -} -#endif /* SQLITE_OMIT_INCRBLOB */ +#endif + + assert( cursorOwnsBtShared(pCur) ); + rc = restoreCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); + rc = accessPayload(pCur, offset, amt, pBuf, 0); + } + return rc; +} /* ** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of ** the key if index btrees (pPage->intKey==0) and is the data for @@ -63795,11 +63014,11 @@ pCur->aiIdx[pCur->iPage] = 0; return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage], pCur, pCur->curPagerFlags); } -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG /* ** Page pParent is an internal (non-leaf) tree page. This function ** asserts that page number iChild is the left-child if the iIdx'th ** cell in page pParent. Or, if iIdx is equal to the total number of ** cells in pParent, that page number iChild is the right-child of @@ -63879,16 +63098,13 @@ } sqlite3BtreeClearCursor(pCur); } if( pCur->iPage>=0 ){ - if( pCur->iPage ){ - do{ - assert( pCur->apPage[pCur->iPage]!=0 ); - releasePageNotNull(pCur->apPage[pCur->iPage--]); - }while( pCur->iPage); - goto skip_init; + while( pCur->iPage ){ + assert( pCur->apPage[pCur->iPage]!=0 ); + releasePageNotNull(pCur->apPage[pCur->iPage--]); } }else if( pCur->pgnoRoot==0 ){ pCur->eState = CURSOR_INVALID; return SQLITE_OK; }else{ @@ -63895,11 +63111,11 @@ assert( pCur->iPage==(-1) ); rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], 0, pCur->curPagerFlags); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; - return rc; + return rc; } pCur->iPage = 0; pCur->curIntKey = pCur->apPage[0]->intKey; } pRoot = pCur->apPage[0]; @@ -63918,16 +63134,14 @@ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ return SQLITE_CORRUPT_BKPT; } -skip_init: pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); - pRoot = pCur->apPage[0]; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ Pgno subpage; if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT; @@ -64112,30 +63326,13 @@ ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; } - if( pCur->info.nKeycurFlags & BTCF_AtLast)!=0 ){ - *pRes = -1; - return SQLITE_OK; - } - /* If the requested key is one more than the previous key, then - ** try to get there using sqlite3BtreeNext() rather than a full - ** binary search. This is an optimization only. The correct answer - ** is still obtained without this ase, only a little more slowely */ - if( pCur->info.nKey+1==intKey && !pCur->skipNext ){ - *pRes = 0; - rc = sqlite3BtreeNext(pCur, pRes); - if( rc ) return rc; - if( *pRes==0 ){ - getCellInfo(pCur); - if( pCur->info.nKey==intKey ){ - return SQLITE_OK; - } - } - } + if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKeyintKey ){ upr = idx-1; if( lwr>upr ){ c = +1; break; } }else{ assert( nCellKey==intKey ); + pCur->curFlags |= BTCF_ValidNKey; + pCur->info.nKey = nCellKey; pCur->aiIdx[pCur->iPage] = (u16)idx; if( !pPage->leaf ){ lwr = idx; goto moveto_next_layer; }else{ - pCur->curFlags |= BTCF_ValidNKey; - pCur->info.nKey = nCellKey; - pCur->info.nSize = 0; *pRes = 0; - return SQLITE_OK; + rc = SQLITE_OK; + goto moveto_finish; } } assert( lwr+upr>=0 ); idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */ } @@ -64267,12 +63464,11 @@ if( pCellKey==0 ){ rc = SQLITE_NOMEM_BKPT; goto moveto_finish; } pCur->aiIdx[pCur->iPage] = (u16)idx; - rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); - pCur->curFlags &= ~BTCF_ValidOvfl; + rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2); if( rc ){ sqlite3_free(pCellKey); goto moveto_finish; } c = xRecordCompare(nCell, pCellKey, pIdxKey); @@ -64318,11 +63514,11 @@ rc = moveToChild(pCur, chldPg); if( rc ) break; } moveto_finish: pCur->info.nSize = 0; - assert( (pCur->curFlags & BTCF_ValidOvfl)==0 ); + pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); return rc; } /* @@ -64338,34 +63534,10 @@ ** as well as the boolean result value. */ return (CURSOR_VALID!=pCur->eState); } -/* -** Return an estimate for the number of rows in the table that pCur is -** pointing to. Return a negative number if no estimate is currently -** available. -*/ -SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){ - i64 n; - u8 i; - - assert( cursorOwnsBtShared(pCur) ); - assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); - - /* Currently this interface is only called by the OP_IfSmaller - ** opcode, and it that case the cursor will always be valid and - ** will always point to a leaf node. */ - if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1; - if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1; - - for(n=1, i=0; i<=pCur->iPage; i++){ - n *= pCur->apPage[i]->nCell; - } - return n; -} - /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. @@ -64540,11 +63712,11 @@ return SQLITE_OK; } moveToParent(pCur); } assert( pCur->info.nSize==0 ); - assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 ); + assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 ); pCur->aiIdx[pCur->iPage]--; pPage = pCur->apPage[pCur->iPage]; if( pPage->intKey && !pPage->leaf ){ rc = sqlite3BtreePrevious(pCur, pRes); @@ -65056,32 +64228,34 @@ ** overflow) into *pnSize. */ static int clearCell( MemPage *pPage, /* The page that contains the Cell */ unsigned char *pCell, /* First byte of the Cell */ - CellInfo *pInfo /* Size information about the cell */ + u16 *pnSize /* Write the size of the Cell here */ ){ BtShared *pBt = pPage->pBt; + CellInfo info; Pgno ovflPgno; int rc; int nOvfl; u32 ovflPageSize; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - pPage->xParseCell(pPage, pCell, pInfo); - if( pInfo->nLocal==pInfo->nPayload ){ + pPage->xParseCell(pPage, pCell, &info); + *pnSize = info.nSize; + if( info.nLocal==info.nPayload ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } - if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ + if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){ return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ } - ovflPgno = get4byte(pCell + pInfo->nSize - 4); + ovflPgno = get4byte(pCell + info.nSize - 4); assert( pBt->usableSize > 4 ); ovflPageSize = pBt->usableSize - 4; - nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize; + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; assert( nOvfl>0 || - (CORRUPT_DB && (pInfo->nPayload + ovflPageSize)btreePagecount(pBt) ){ @@ -65206,11 +64380,11 @@ ** pPrior Where to write the pgno of the first overflow page ** ** Use a call to btreeParseCellPtr() to verify that the values above ** were computed correctly. */ -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG { CellInfo info; pPage->xParseCell(pPage, pCell, &info); assert( nHeader==(int)(info.pPayload - pCell) ); assert( info.nKey==pX->nKey ); @@ -65317,10 +64491,11 @@ u8 *ptr; /* Used to move bytes around within data[] */ int rc; /* The return code */ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; + assert( idx>=0 && idxnCell ); assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); data = pPage->aData; @@ -65400,14 +64575,11 @@ } if( iChild ){ put4byte(pCell, iChild); } j = pPage->nOverflow++; - /* Comparison against ArraySize-1 since we hold back one extra slot - ** as a contingency. In other words, never need more than 3 overflow - ** slots but 4 are allocated, just to be safe. */ - assert( j < ArraySize(pPage->apOvfl)-1 ); + assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); pPage->apOvfl[j] = pCell; pPage->aiOvfl[j] = (u16)i; /* When multiple overflows occur, they are always sequential and in ** sorted order. This invariants arise because multiple overflows can @@ -66143,11 +65315,11 @@ goto balance_cleanup; } nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; if( (i--)==0 ) break; - if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ + if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); szNew[i] = pParent->xCellSize(pParent, apDiv[i]); pParent->nOverflow = 0; }else{ @@ -66335,10 +65507,11 @@ */ usableSpace = pBt->usableSize - 12 + leafCorrection; for(i=0; inFree; + if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } for(j=0; jnOverflow; j++){ szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]); } cntNew[i] = cntOld[i]; } @@ -66732,11 +65905,11 @@ ** copied into the parent, because if the parent is page 1 then it will ** by smaller than the child due to the database header, and so all the ** free space needs to be up front. */ assert( nNew==1 || CORRUPT_DB ); - rc = defragmentPage(apNew[0], -1); + rc = defragmentPage(apNew[0]); testcase( rc!=SQLITE_OK ); assert( apNew[0]->nFree == (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) || rc!=SQLITE_OK ); @@ -66996,28 +66169,26 @@ ** For an index btree (used for indexes and WITHOUT ROWID tables), the ** key is an arbitrary byte sequence stored in pX.pKey,nKey. The ** pX.pData,nData,nZero fields must be zero. ** ** If the seekResult parameter is non-zero, then a successful call to -** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already -** been performed. In other words, if seekResult!=0 then the cursor -** is currently pointing to a cell that will be adjacent to the cell -** to be inserted. If seekResult<0 then pCur points to a cell that is -** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell -** that is larger than (pKey,nKey). +** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already +** been performed. seekResult is the search result returned (a negative +** number if pCur points at an entry that is smaller than (pKey, nKey), or +** a positive value if pCur points at an entry that is larger than +** (pKey, nKey)). ** -** If seekResult==0, that means pCur is pointing at some unknown location. -** In that case, this routine must seek the cursor to the correct insertion -** point for (pKey,nKey) before doing the insertion. For index btrees, -** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked -** key values and pX->aMem can be used instead of pX->pKey to avoid having -** to decode the key. +** If the seekResult parameter is non-zero, then the caller guarantees that +** cursor pCur is pointing at the existing copy of a row that is to be +** overwritten. If the seekResult parameter is 0, then cursor pCur may +** point to any entry or to no entry at all and so this function has to seek +** the cursor before the new key can be inserted. */ SQLITE_PRIVATE int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const BtreePayload *pX, /* Content of the row to be inserted */ - int flags, /* True if this is likely an append */ + int appendBias, /* True if this is likely an append */ int seekResult /* Result of prior MovetoUnpacked() call */ ){ int rc; int loc = seekResult; /* -1: before desired location +1: after */ int szNew = 0; @@ -67026,12 +66197,10 @@ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; unsigned char *oldCell; unsigned char *newCell = 0; - assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags ); - if( pCur->eState==CURSOR_FAULT ){ assert( pCur->skipNext!=SQLITE_OK ); return pCur->skipNext; } @@ -67068,42 +66237,22 @@ assert( pX->pKey==0 ); /* If this is an insert into a table b-tree, invalidate any incrblob ** cursors open on the row being replaced */ invalidateIncrblobCursors(p, pX->nKey, 0); - /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing - ** to a row with the same key as the new entry being inserted. */ - assert( (flags & BTREE_SAVEPOSITION)==0 || - ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) ); - /* If the cursor is currently on the last row and we are appending a ** new row onto the end, set the "loc" to avoid an unnecessary ** btreeMoveto() call */ - if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){ - loc = 0; - }else if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 - && pCur->info.nKey==pX->nKey-1 ){ - loc = -1; + if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0 + && pCur->info.nKey==pX->nKey-1 ){ + loc = -1; }else if( loc==0 ){ - rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc); + rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc); if( rc ) return rc; } - }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){ - if( pX->nMem ){ - UnpackedRecord r; - r.pKeyInfo = pCur->pKeyInfo; - r.aMem = pX->aMem; - r.nField = pX->nMem; - r.default_rc = 0; - r.errCode = 0; - r.r1 = 0; - r.r2 = 0; - r.eqSeen = 0; - rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc); - }else{ - rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc); - } + }else if( loc==0 ){ + rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc); if( rc ) return rc; } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); pPage = pCur->apPage[pCur->iPage]; @@ -67120,33 +66269,22 @@ if( rc ) goto end_insert; assert( szNew==pPage->xCellSize(pPage, newCell) ); assert( szNew <= MX_CELL_SIZE(pBt) ); idx = pCur->aiIdx[pCur->iPage]; if( loc==0 ){ - CellInfo info; + u16 szOld; assert( idxnCell ); rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ){ goto end_insert; } oldCell = findCell(pPage, idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } - rc = clearCell(pPage, oldCell, &info); - if( info.nSize==szNew && info.nLocal==info.nPayload ){ - /* Overwrite the old cell with the new if they are the same size. - ** We could also try to do this if the old cell is smaller, then add - ** the leftover space to the free list. But experiments show that - ** doing that is no faster then skipping this optimization and just - ** calling dropCell() and insertCell(). */ - assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ - if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; - memcpy(oldCell, newCell, szNew); - return SQLITE_OK; - } - dropCell(pPage, idx, info.nSize, &rc); + rc = clearCell(pPage, oldCell, &szOld); + dropCell(pPage, idx, szOld, &rc); if( rc ) goto end_insert; }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->aiIdx[pCur->iPage]; }else{ @@ -67186,24 +66324,10 @@ ** fails. Internal data structure corruption will result otherwise. ** Also, set the cursor state to invalid. This stops saveCursorPosition() ** from trying to save the current position of the cursor. */ pCur->apPage[pCur->iPage]->nOverflow = 0; pCur->eState = CURSOR_INVALID; - if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){ - rc = moveToRoot(pCur); - if( pCur->pKeyInfo ){ - assert( pCur->pKey==0 ); - pCur->pKey = sqlite3Malloc( pX->nKey ); - if( pCur->pKey==0 ){ - rc = SQLITE_NOMEM; - }else{ - memcpy(pCur->pKey, pX->pKey, pX->nKey); - } - } - pCur->eState = CURSOR_REQUIRESEEK; - pCur->nKey = pX->nKey; - } } assert( pCur->apPage[pCur->iPage]->nOverflow==0 ); end_insert: return rc; @@ -67232,11 +66356,11 @@ int rc; /* Return code */ MemPage *pPage; /* Page to delete cell from */ unsigned char *pCell; /* Pointer to cell to delete */ int iCellIdx; /* Index of cell to delete */ int iCellDepth; /* Depth of node containing pCell */ - CellInfo info; /* Size of the cell being deleted */ + u16 szCell; /* Size of the cell being deleted */ int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ assert( cursorOwnsBtShared(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -67304,12 +66428,12 @@ /* Make the page containing the entry to be deleted writable. Then free any ** overflow pages associated with the entry and finally remove the cell ** itself from within the page. */ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; - rc = clearCell(pPage, pCell, &info); - dropCell(pPage, iCellIdx, info.nSize, &rc); + rc = clearCell(pPage, pCell, &szCell); + dropCell(pPage, iCellIdx, szCell, &rc); if( rc ) return rc; /* If the cell deleted was not located on a leaf page, then the cursor ** is currently pointing to the largest entry in the sub-tree headed ** by the child-page of the cell that was just deleted from an internal @@ -67555,11 +66679,11 @@ MemPage *pPage; int rc; unsigned char *pCell; int i; int hdr; - CellInfo info; + u16 szCell; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } @@ -67575,11 +66699,11 @@ pCell = findCell(pPage, i); if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } - rc = clearCell(pPage, pCell, &info); + rc = clearCell(pPage, pCell, &szCell); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; @@ -67666,11 +66790,31 @@ MemPage *pPage = 0; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); assert( p->inTrans==TRANS_WRITE ); - assert( iTable>=2 ); + + /* It is illegal to drop a table if any cursors are open on the + ** database. This is because in auto-vacuum mode the backend may + ** need to move another root-page to fill a gap left by the deleted + ** root page. If an open cursor was using this page a problem would + ** occur. + ** + ** This error is caught long before control reaches this point. + */ + if( NEVER(pBt->pCursor) ){ + sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db); + return SQLITE_LOCKED_SHAREDCACHE; + } + + /* + ** It is illegal to drop the sqlite_master table on page 1. But again, + ** this error is caught long before reaching this point. + */ + if( NEVER(iTable<2) ){ + return SQLITE_CORRUPT_BKPT; + } rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; rc = sqlite3BtreeClearTable(p, iTable, 0); if( rc ){ @@ -68574,11 +67718,11 @@ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); if( pBt->inTransaction!=TRANS_NONE ){ rc = SQLITE_LOCKED; }else{ - rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt); + rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt); } sqlite3BtreeLeave(p); } return rc; } @@ -70550,13 +69694,14 @@ 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 +** The data or key is taken from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. -** The result is written into the pMem element. +** key is true to get the key or false to get data. The result is written +** into the pMem element. ** ** The pMem object must have been initialized. This routine will use ** pMem->zMalloc to hold the content from the btree, if possible. New ** pMem->zMalloc space will be allocated if necessary. The calling routine ** is responsible for making sure that the pMem object is eventually @@ -70567,16 +69712,21 @@ */ static SQLITE_NOINLINE int vdbeMemFromBtreeResize( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ + int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ int rc; pMem->flags = MEM_Null; if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){ - rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z); + if( key ){ + rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); + }else{ + rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); + } if( rc==SQLITE_OK ){ pMem->z[amt] = 0; pMem->z[amt+1] = 0; pMem->flags = MEM_Blob|MEM_Term; pMem->n = (int)amt; @@ -70588,10 +69738,11 @@ } SQLITE_PRIVATE int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ u32 offset, /* Offset from the start of data to return bytes from. */ u32 amt, /* Number of bytes to return. */ + int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ u32 available = 0; /* Number of bytes available on the local btree page */ int rc = SQLITE_OK; /* Return code */ @@ -70608,11 +69759,11 @@ if( offset+amt<=available ){ pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; pMem->n = (int)amt; }else{ - rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem); + rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem); } return rc; } @@ -70626,11 +69777,10 @@ assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); assert( (pVal->flags & MEM_RowSet)==0 ); assert( (pVal->flags & (MEM_Null))==0 ); if( pVal->flags & (MEM_Blob|MEM_Str) ){ - if( ExpandBlob(pVal) ) return 0; pVal->flags |= MEM_Str; if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); } if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&SQLITE_PTR_TO_INT(pVal->z)) ){ @@ -70950,11 +70100,10 @@ sqlite3ValueApplyAffinity(pVal, affinity, enc); } }else if( op==TK_NULL ){ pVal = valueNew(db, pCtx); if( pVal==0 ) goto no_mem; - sqlite3VdbeMemNumerify(pVal); } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); @@ -71384,11 +70533,10 @@ ** Remember the SQL string for a prepared statement. */ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ assert( isPrepareV2==1 || isPrepareV2==0 ); if( p==0 ) return; - if( !isPrepareV2 ) p->expmask = 0; #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) if( !isPrepareV2 ) return; #endif assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); @@ -71413,11 +70561,10 @@ pB->pPrev = pTmp; zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; pB->isPrepareV2 = pA->isPrepareV2; - pB->expmask = pA->expmask; } /* ** Resize the Vdbe.aOp array so that it is at least nOp elements larger ** than its current size. nOp is guaranteed to be less than or equal @@ -71444,16 +70591,10 @@ #else int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); UNUSED_PARAMETER(nOp); #endif - /* Ensure that the size of a VDBE does not grow too large */ - if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){ - sqlite3OomFault(p->db); - return SQLITE_NOMEM; - } - assert( nOp<=(1024/sizeof(Op)) ); assert( nNew>=(p->nOpAlloc+nOp) ); pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); if( pNew ){ p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew); @@ -71648,15 +70789,11 @@ int p2, /* The P2 operand */ int p3, /* The P3 operand */ int p4 /* The P4 operand as an integer */ ){ int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3); - if( p->db->mallocFailed==0 ){ - VdbeOp *pOp = &p->aOp[addr]; - pOp->p4type = P4_INT32; - pOp->p4.i = p4; - } + sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32); return addr; } /* Insert the end of a co-routine */ @@ -71983,26 +71120,10 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){ assert( p->nOp + N <= p->pParse->nOpAlloc ); } #endif -/* -** Verify that the VM passed as the only argument does not contain -** an OP_ResultRow opcode. Fail an assert() if it does. This is used -** by code in pragma.c to ensure that the implementation of certain -** pragmas comports with the flags specified in the mkpragmatab.tcl -** script. -*/ -#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS) -SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p){ - int i; - for(i=0; inOp; i++){ - assert( p->aOp[i].opcode!=OP_ResultRow ); - } -} -#endif - /* ** This function returns a pointer to the array of opcodes associated with ** the Vdbe passed as the first argument. It is the callers responsibility ** to arrange for the returned array to be eventually freed using the ** vdbeFreeOpArray() function. @@ -72118,11 +71239,11 @@ sqlite3VdbeGetOp(p,addr)->p2 = val; } SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){ sqlite3VdbeGetOp(p,addr)->p3 = val; } -SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){ assert( p->nOp>0 || p->db->mallocFailed ); if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } /* @@ -72179,10 +71300,14 @@ case P4_EXPR: { sqlite3ExprDelete(db, (Expr*)p4); break; } #endif + case P4_MPRINTF: { + if( db->pnBytesFreed==0 ) sqlite3_free(p4); + break; + } case P4_FUNCDEF: { freeEphemeralFunction(db, (FuncDef*)p4); break; } case P4_MEM: { @@ -72323,46 +71448,20 @@ pOp->p4type = (signed char)n; if( n==P4_VTAB ) sqlite3VtabLock((VTable*)zP4); } } -/* -** Change the P4 operand of the most recently coded instruction -** to the value defined by the arguments. This is a high-speed -** version of sqlite3VdbeChangeP4(). -** -** The P4 operand must not have been previously defined. And the new -** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of -** those cases. -*/ -SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){ - VdbeOp *pOp; - assert( n!=P4_INT32 && n!=P4_VTAB ); - assert( n<=0 ); - if( p->db->mallocFailed ){ - freeP4(p->db, n, pP4); - }else{ - assert( pP4!=0 ); - assert( p->nOp>0 ); - pOp = &p->aOp[p->nOp-1]; - assert( pOp->p4type==P4_NOTUSED ); - pOp->p4type = n; - pOp->p4.p = pP4; - } -} - /* ** Set the P4 on the most recently added opcode to the KeyInfo for the ** index given. */ SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){ Vdbe *v = pParse->pVdbe; - KeyInfo *pKeyInfo; assert( v!=0 ); assert( pIdx!=0 ); - pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pIdx); - if( pKeyInfo ) sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); + sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx), + P4_KEYINFO); } #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS /* ** Change the comment on the most recently coded instruction. Or @@ -72648,11 +71747,11 @@ case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } -#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) +#ifdef SQLITE_DEBUG case P4_FUNCCTX: { FuncDef *pDef = pOp->p4.pCtx->pFunc; sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg); break; } @@ -73326,12 +72425,14 @@ if( x.nNeeded==0 ) break; x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded); x.nFree = x.nNeeded; }while( !db->mallocFailed ); - p->pVList = pParse->pVList; - pParse->pVList = 0; + p->nzVar = pParse->nzVar; + p->azVar = pParse->azVar; + pParse->nzVar = 0; + pParse->azVar = 0; p->explain = pParse->explain; if( db->mallocFailed ){ p->nVar = 0; p->nCursor = 0; p->nMem = 0; @@ -73355,19 +72456,19 @@ */ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx==0 ){ return; } - assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE ); + assert( pCx->pBt==0 || pCx->eCurType==CURTYPE_BTREE ); switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); break; } case CURTYPE_BTREE: { - if( pCx->pBtx ){ - sqlite3BtreeClose(pCx->pBtx); + if( pCx->pBt ){ + sqlite3BtreeClose(pCx->pBt); /* The pCx->pCursor will be close automatically, if it exists, by ** the call above. */ }else{ assert( pCx->uc.pCursor!=0 ); sqlite3BtreeCloseCursor(pCx->uc.pCursor); @@ -73832,63 +72933,64 @@ ** statement transaction is committed. ** ** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned. ** Otherwise SQLITE_OK. */ -static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){ +SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ sqlite3 *const db = p->db; int rc = SQLITE_OK; - int i; - const int iSavepoint = p->iStatement-1; - - assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); - assert( db->nStatement>0 ); - assert( p->iStatement==(db->nStatement+db->nSavepoint) ); - - for(i=0; inDb; i++){ - int rc2 = SQLITE_OK; - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - if( eOp==SAVEPOINT_ROLLBACK ){ - rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint); - } - if( rc2==SQLITE_OK ){ - rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint); - } - if( rc==SQLITE_OK ){ - rc = rc2; - } - } - } - db->nStatement--; - p->iStatement = 0; - - if( rc==SQLITE_OK ){ - if( eOp==SAVEPOINT_ROLLBACK ){ - rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint); - } - if( rc==SQLITE_OK ){ - rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint); - } - } - - /* If the statement transaction is being rolled back, also restore the - ** database handles deferred constraint counter to the value it had when - ** the statement transaction was opened. */ - if( eOp==SAVEPOINT_ROLLBACK ){ - db->nDeferredCons = p->nStmtDefCons; - db->nDeferredImmCons = p->nStmtDefImmCons; - } - return rc; -} -SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ - if( p->db->nStatement && p->iStatement ){ - return vdbeCloseStatement(p, eOp); - } - return SQLITE_OK; -} - + + /* If p->iStatement is greater than zero, then this Vdbe opened a + ** statement transaction that should be closed here. The only exception + ** is that an IO error may have occurred, causing an emergency rollback. + ** In this case (db->nStatement==0), and there is nothing to do. + */ + if( db->nStatement && p->iStatement ){ + int i; + const int iSavepoint = p->iStatement-1; + + assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE); + assert( db->nStatement>0 ); + assert( p->iStatement==(db->nStatement+db->nSavepoint) ); + + for(i=0; inDb; i++){ + int rc2 = SQLITE_OK; + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + if( eOp==SAVEPOINT_ROLLBACK ){ + rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint); + } + if( rc2==SQLITE_OK ){ + rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint); + } + if( rc==SQLITE_OK ){ + rc = rc2; + } + } + } + db->nStatement--; + p->iStatement = 0; + + if( rc==SQLITE_OK ){ + if( eOp==SAVEPOINT_ROLLBACK ){ + rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint); + } + if( rc==SQLITE_OK ){ + rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint); + } + } + + /* If the statement transaction is being rolled back, also restore the + ** database handles deferred constraint counter to the value it had when + ** the statement transaction was opened. */ + if( eOp==SAVEPOINT_ROLLBACK ){ + db->nDeferredCons = p->nStmtDefCons; + db->nDeferredImmCons = p->nStmtDefImmCons; + } + } + return rc; +} /* ** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be ** committed. If there are outstanding deferred foreign key constraint @@ -73944,17 +73046,17 @@ ** Then the internal cache might have been left in an inconsistent ** state. We need to rollback the statement transaction, if there is ** one, or the complete transaction if there is no statement transaction. */ - if( p->magic!=VDBE_MAGIC_RUN ){ - return SQLITE_OK; - } if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; } closeAllCursors(p); + if( p->magic!=VDBE_MAGIC_RUN ){ + return SQLITE_OK; + } checkActiveVdbeCnt(db); /* No commit or rollback needed if the program never started or if the ** SQL statement does not read or write a database file. */ if( p->pc>=0 && p->bIsReader ){ @@ -74320,33 +73422,32 @@ ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with ** the database connection and frees the object itself. */ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; + int i; assert( p->db==0 || p->db==db ); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } if( p->magic!=VDBE_MAGIC_INIT ){ releaseMemArray(p->aVar, p->nVar); - sqlite3DbFree(db, p->pVList); + for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); + sqlite3DbFree(db, p->azVar); sqlite3DbFree(db, p->pFree); } vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - { - int i; - for(i=0; inScan; i++){ - sqlite3DbFree(db, p->aScan[i].zName); - } - sqlite3DbFree(db, p->aScan); + for(i=0; inScan; i++){ + sqlite3DbFree(db, p->aScan[i].zName); } + sqlite3DbFree(db, p->aScan); #endif } /* ** Delete an entire VDBE. @@ -74843,17 +73944,34 @@ ** before returning. ** ** If an OOM error occurs, NULL is returned. */ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( - KeyInfo *pKeyInfo /* Description of the record */ + KeyInfo *pKeyInfo, /* Description of the record */ + char *pSpace, /* Unaligned space available */ + int szSpace, /* Size of pSpace[] in bytes */ + char **ppFree /* OUT: Caller should free this pointer */ ){ UnpackedRecord *p; /* Unpacked record to return */ + int nOff; /* Increment pSpace by nOff to align it */ int nByte; /* Number of bytes required for *p */ + + /* We want to shift the pointer pSpace up such that it is 8-byte aligned. + ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift + ** it by. If pSpace is already 8-byte aligned, nOff should be zero. + */ + nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7; nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1); - p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); - if( !p ) return 0; + if( nByte>szSpace+nOff ){ + p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); + *ppFree = (char *)p; + if( !p ) return 0; + }else{ + p = (UnpackedRecord*)&pSpace[nOff]; + *ppFree = 0; + } + p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; assert( pKeyInfo->aSortOrder!=0 ); p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nField + 1; return p; @@ -74897,11 +74015,11 @@ } assert( u<=pKeyInfo->nField + 1 ); p->nField = u; } -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG /* ** This function compares two index or table record keys in the same way ** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(), ** this function deserializes and compares values using the ** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used @@ -75002,11 +74120,11 @@ if( pKeyInfo->db->mallocFailed ) return 1; return 0; } #endif -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG /* ** Count the number of fields (a.k.a. columns) in the record given by ** pKey,nKey. The verify that this count is less than or equal to the ** limit given by pKeyInfo->nField + pKeyInfo->nXField. ** @@ -75723,11 +74841,11 @@ nCellKey = sqlite3BtreePayloadSize(pCur); assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); /* Read in the complete content of the index entry */ sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m); + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m); if( rc ){ return rc; } /* The index entry must begin with a header size */ @@ -75803,11 +74921,11 @@ if( nCellKey<=0 || nCellKey>0x7fffffff ){ *res = 0; return SQLITE_CORRUPT_BKPT; } sqlite3VdbeMemInit(&m, db, 0); - rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m); + rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m); if( rc ){ return rc; } *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); sqlite3VdbeMemRelease(&m); @@ -75885,12 +75003,12 @@ ** to sqlite3_reoptimize() that re-preparing the statement may result ** in a better query plan. */ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ assert( iVar>0 ); - if( iVar>=32 ){ - v->expmask |= 0x80000000; + if( iVar>32 ){ + v->expmask = 0xffffffff; }else{ v->expmask |= ((u32)1 << (iVar-1)); } } @@ -75919,14 +75037,14 @@ ** structure itself, using sqlite3DbFree(). ** ** This function is used to free UnpackedRecord structures allocated by ** the vdbeUnpackRecord() function found in vdbeapi.c. */ -static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){ +static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){ if( p ){ int i; - for(i=0; inField; i++){ Mem *pMem = &p->aMem[i]; if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); } sqlite3DbFree(db, p); } @@ -75955,19 +75073,14 @@ const char *zTbl = pTab->zName; static const u8 fakeSortOrder = 0; assert( db->pPreUpdate==0 ); memset(&preupdate, 0, sizeof(PreUpdate)); - if( HasRowid(pTab)==0 ){ - iKey1 = iKey2 = 0; - preupdate.pPk = sqlite3PrimaryKeyIndex(pTab); - }else{ - if( op==SQLITE_UPDATE ){ - iKey2 = v->aMem[iReg].u.i; - }else{ - iKey2 = iKey1; - } + if( op==SQLITE_UPDATE ){ + iKey2 = v->aMem[iReg].u.i; + }else{ + iKey2 = iKey1; } assert( pCsr->nField==pTab->nCol || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) ); @@ -75986,12 +75099,12 @@ db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); - vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked); - vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked); + vdbeFreeUnpacked(db, preupdate.pUnpacked); + vdbeFreeUnpacked(db, preupdate.pNewUnpacked); if( preupdate.aNew ){ int i; for(i=0; inField; i++){ sqlite3VdbeMemRelease(&preupdate.aNew[i]); } @@ -76156,12 +75269,11 @@ sqlite3_mutex_enter(mutex); for(i=0; inVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); p->aVar[i].flags = MEM_Null; } - assert( p->isPrepareV2 || p->expmask==0 ); - if( p->expmask ){ + if( p->isPrepareV2 && p->expmask ){ p->expired = 1; } sqlite3_mutex_leave(mutex); return rc; } @@ -77261,12 +76373,13 @@ ** parameter in the WHERE clause might influence the choice of query plan ** for a statement, then the statement will be automatically recompiled, ** as if there had been a schema change, on the first sqlite3_step() call ** following any change to the bindings of that parameter. */ - assert( p->isPrepareV2 || p->expmask==0 ); - if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<isPrepareV2 && + ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) + ){ p->expired = 1; } return SQLITE_OK; } @@ -77472,22 +76585,35 @@ ** ** The result is always UTF-8. */ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ Vdbe *p = (Vdbe*)pStmt; - if( p==0 ) return 0; - return sqlite3VListNumToName(p->pVList, i); + if( p==0 || i<1 || i>p->nzVar ){ + return 0; + } + return p->azVar[i-1]; } /* ** Given a wildcard parameter name, return the index of the variable ** with that name. If there is no variable with the given name, ** return 0. */ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){ - if( p==0 || zName==0 ) return 0; - return sqlite3VListNameToNum(p->pVList, zName, nName); + int i; + if( p==0 ){ + return 0; + } + if( zName ){ + for(i=0; inzVar; i++){ + const char *z = p->azVar[i]; + if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){ + return i+1; + } + } + } + return 0; } SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName)); } @@ -77525,16 +76651,14 @@ Vdbe *pFrom = (Vdbe*)pFromStmt; Vdbe *pTo = (Vdbe*)pToStmt; if( pFrom->nVar!=pTo->nVar ){ return SQLITE_ERROR; } - assert( pTo->isPrepareV2 || pTo->expmask==0 ); - if( pTo->expmask ){ + if( pTo->isPrepareV2 && pTo->expmask ){ pTo->expired = 1; } - assert( pFrom->isPrepareV2 || pFrom->expmask==0 ); - if( pFrom->expmask ){ + if( pFrom->isPrepareV2 && pFrom->expmask ){ pFrom->expired = 1; } return sqlite3TransferBindings(pFromStmt, pToStmt); } #endif @@ -77648,13 +76772,14 @@ static UnpackedRecord *vdbeUnpackRecord( KeyInfo *pKeyInfo, int nKey, const void *pKey ){ + char *dummy; /* Dummy argument for AllocUnpackedRecord() */ UnpackedRecord *pRet; /* Return value */ - pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); + pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy); if( pRet ){ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1)); sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet); } return pRet; @@ -77664,22 +76789,18 @@ ** This function is called from within a pre-update callback to retrieve ** a field of the row currently being updated or deleted. */ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ PreUpdate *p = db->pPreUpdate; - Mem *pMem; int rc = SQLITE_OK; /* Test that this call is being made from within an SQLITE_DELETE or ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */ if( !p || p->op==SQLITE_INSERT ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_old_out; } - if( p->pPk ){ - iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx); - } if( iIdx>=p->pCsr->nField || iIdx<0 ){ rc = SQLITE_RANGE; goto preupdate_old_out; } @@ -77689,11 +76810,11 @@ u8 *aRec; nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor); aRec = sqlite3DbMallocRaw(db, nRec); if( !aRec ) goto preupdate_old_out; - rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec); + rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec); if( rc==SQLITE_OK ){ p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec); if( !p->pUnpacked ) rc = SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ @@ -77701,18 +76822,21 @@ goto preupdate_old_out; } p->aRecord = aRec; } - pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; - if( iIdx==p->pTab->iPKey ){ - sqlite3VdbeMemSetInt64(pMem, p->iKey1); - }else if( iIdx>=p->pUnpacked->nField ){ + if( iIdx>=p->pUnpacked->nField ){ *ppValue = (sqlite3_value *)columnNullValue(); - }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ - if( pMem->flags & MEM_Int ){ - sqlite3VdbeMemRealify(pMem); + }else{ + Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx]; + *ppValue = &p->pUnpacked->aMem[iIdx]; + if( iIdx==p->pTab->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey1); + }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){ + if( pMem->flags & MEM_Int ){ + sqlite3VdbeMemRealify(pMem); + } } } preupdate_old_out: sqlite3Error(db, rc); @@ -77761,13 +76885,10 @@ if( !p || p->op==SQLITE_DELETE ){ rc = SQLITE_MISUSE_BKPT; goto preupdate_new_out; } - if( p->pPk && p->op!=SQLITE_UPDATE ){ - iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx); - } if( iIdx>=p->pCsr->nField || iIdx<0 ){ rc = SQLITE_RANGE; goto preupdate_new_out; } @@ -77784,15 +76905,17 @@ rc = SQLITE_NOMEM; goto preupdate_new_out; } p->pNewUnpacked = pUnpack; } - pMem = &pUnpack->aMem[iIdx]; - if( iIdx==p->pTab->iPKey ){ - sqlite3VdbeMemSetInt64(pMem, p->iKey2); - }else if( iIdx>=pUnpack->nField ){ + if( iIdx>=pUnpack->nField ){ pMem = (sqlite3_value *)columnNullValue(); + }else{ + pMem = &pUnpack->aMem[iIdx]; + if( iIdx==p->pTab->iPKey ){ + sqlite3VdbeMemSetInt64(pMem, p->iKey2); + } } }else{ /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required ** value. Make a copy of the cell contents and return a pointer to it. ** It is not safe to return a pointer to the memory cell itself as the @@ -78204,11 +77327,11 @@ /* ** Test a register to see if it exceeds the current maximum blob size. ** If it does, record the new maximum blob size. */ -#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE) +#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST) # define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) #else # define UPDATE_MAX_BLOBSIZE(P) #endif @@ -78314,11 +77437,11 @@ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; - memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); + memset(pCx, 0, sizeof(VdbeCursor)); pCx->eCurType = eCurType; pCx->iDb = iDb; pCx->nField = nField; pCx->aOffset = &pCx->aType[nField]; if( eCurType==CURTYPE_BTREE ){ @@ -78496,11 +77619,13 @@ c = 'e'; assert( (f & (MEM_Static|MEM_Dyn))==0 ); }else{ c = 's'; } - *(zCsr++) = c; + + sqlite3_snprintf(100, zCsr, "%c", c); + zCsr += sqlite3Strlen30(zCsr); sqlite3_snprintf(100, zCsr, "%d[", pMem->n); zCsr += sqlite3Strlen30(zCsr); for(i=0; i<16 && in; i++){ sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); zCsr += sqlite3Strlen30(zCsr); @@ -78508,11 +77633,13 @@ for(i=0; i<16 && in; i++){ char z = pMem->z[i]; if( z<32 || z>126 ) *zCsr++ = '.'; else *zCsr++ = z; } - *(zCsr++) = ']'; + + sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]); + zCsr += sqlite3Strlen30(zCsr); if( f & MEM_Zero ){ sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero); zCsr += sqlite3Strlen30(zCsr); } *zCsr = '\0'; @@ -78761,10 +77888,12 @@ Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ + int *aPermute = 0; /* Permutation of columns for OP_Compare */ + i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ #ifdef VDBE_PROFILE u64 start; /* CPU clock count at start of opcode */ #endif /*** INSERT STACK UNION HERE ***/ @@ -78775,10 +77904,11 @@ ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY ); assert( p->bIsReader || p->readOnly!=0 ); + p->rc = SQLITE_OK; p->iCurrentTime = 0; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; if( db->u1.isInterrupted ) goto abort_due_to_interrupt; @@ -79135,10 +78265,11 @@ pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); pcx = sqlite3VdbeFrameRestore(pFrame); + lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ /* Instruction pcx is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified @@ -79151,11 +78282,11 @@ break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; p->pc = pcx; - assert( pOp->p5<=4 ); + assert( pOp->p5>=0 && pOp->p5<=4 ); if( p->rc ){ if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", "FOREIGN KEY" }; testcase( pOp->p5==1 ); @@ -79364,16 +78495,16 @@ */ case OP_Variable: { /* out2 */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); - assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) ); + assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] ); pVar = &p->aVar[pOp->p1 - 1]; if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } - pOut = &aMem[pOp->p2]; + pOut = out2Prerelease(p, pOp); sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; } @@ -79847,39 +78978,41 @@ if( pCtx->pOut != pOut ){ pCtx->pOut = pOut; for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; } - memAboutToChange(p, pOut); + memAboutToChange(p, pCtx->pOut); #ifdef SQLITE_DEBUG for(i=0; iargc; i++){ assert( memIsValid(pCtx->argv[i]) ); REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]); } #endif - MemSetTypeFlag(pOut, MEM_Null); + MemSetTypeFlag(pCtx->pOut, MEM_Null); pCtx->fErrorOrAux = 0; + db->lastRowid = lastRowid; (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ + lastRowid = db->lastRowid; /* Remember rowid changes made by xSFunc */ /* If the function returned an error, throw an exception */ if( pCtx->fErrorOrAux ){ if( pCtx->isError ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); + sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); rc = pCtx->isError; } sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); if( rc ) goto abort_due_to_error; } /* Copy the result of the function into register P3 */ if( pOut->flags & (MEM_Str|MEM_Blob) ){ - sqlite3VdbeChangeEncoding(pOut, encoding); - if( sqlite3VdbeMemTooBig(pOut) ) goto too_big; + sqlite3VdbeChangeEncoding(pCtx->pOut, encoding); + if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big; } - REGISTER_TRACE(pOp->p3, pOut); - UPDATE_MAX_BLOBSIZE(pOut); + REGISTER_TRACE(pOp->p3, pCtx->pOut); + UPDATE_MAX_BLOBSIZE(pCtx->pOut); break; } /* Opcode: BitAnd P1 P2 P3 * * ** Synopsis: r[P3]=r[P1]&r[P2] @@ -80175,11 +79308,12 @@ ** or not both operands are null. */ assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 ); - if( (flags1&flags3&MEM_Null)!=0 + if( (flags1&MEM_Null)!=0 + && (flags3&MEM_Null)!=0 && (flags3&MEM_Cleared)==0 ){ res = 0; /* Operands are equal */ }else{ res = 1; /* Operands are not equal */ @@ -80312,12 +79446,12 @@ } /* Opcode: Permutation * * * P4 * ** -** Set the permutation used by the OP_Compare operator in the next -** instruction. The permutation is stored in the P4 operand. +** Set the permutation used by the OP_Compare operator to be the array +** of integers in P4. ** ** The permutation is only valid until the next OP_Compare that has ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should ** occur immediately prior to the OP_Compare. ** @@ -80325,12 +79459,11 @@ ** and does not become part of the permutation. */ case OP_Permutation: { assert( pOp->p4type==P4_INTARRAY ); assert( pOp->p4.ai ); - assert( pOp[1].opcode==OP_Compare ); - assert( pOp[1].p5 & OPFLAG_PERMUTE ); + aPermute = pOp->p4.ai + 1; break; } /* Opcode: Compare P1 P2 P3 P4 P5 ** Synopsis: r[P1@P3] <-> r[P2@P3] @@ -80359,28 +79492,19 @@ int p2; const KeyInfo *pKeyInfo; int idx; CollSeq *pColl; /* Collating sequence to use on this term */ int bRev; /* True for DESCENDING sort order */ - int *aPermute; /* The permutation */ - - if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){ - aPermute = 0; - }else{ - assert( pOp>aOp ); - assert( pOp[-1].opcode==OP_Permutation ); - assert( pOp[-1].p4type==P4_INTARRAY ); - aPermute = pOp[-1].p4.ai + 1; - assert( aPermute!=0 ); - } + + if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; n = pOp->p3; pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); p1 = pOp->p1; p2 = pOp->p2; -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG if( aPermute ){ int k, mx = 0; for(k=0; kmx ) mx = aPermute[k]; assert( p1>0 && p1+mx<=(p->nMem+1 - p->nCursor)+1 ); assert( p2>0 && p2+mx<=(p->nMem+1 - p->nCursor)+1 ); @@ -80402,10 +79526,11 @@ if( iCompare ){ if( bRev ) iCompare = -iCompare; break; } } + aPermute = 0; break; } /* Opcode: Jump P1 P2 P3 * * ** @@ -80514,43 +79639,23 @@ break; } /* Opcode: Once P1 P2 * * * ** -** Fall through to the next instruction the first time this opcode is -** encountered on each invocation of the byte-code program. Jump to P2 -** on the second and all subsequent encounters during the same invocation. -** -** Top-level programs determine first invocation by comparing the P1 -** operand against the P1 operand on the OP_Init opcode at the beginning -** of the program. If the P1 values differ, then fall through and make -** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are -** the same then take the jump. -** -** For subprograms, there is a bitmask in the VdbeFrame that determines -** whether or not the jump should be taken. The bitmask is necessary -** because the self-altering code trick does not work for recursive -** triggers. +** If the P1 value is equal to the P1 value on the OP_Init opcode at +** instruction 0, then jump to P2. If the two P1 values differ, then +** set the P1 value on this opcode to equal the P1 value on the OP_Init +** and fall through. */ case OP_Once: { /* jump */ - u32 iAddr; /* Address of this instruction */ assert( p->aOp[0].opcode==OP_Init ); - if( p->pFrame ){ - iAddr = (int)(pOp - p->aOp); - if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){ - VdbeBranchTaken(1, 2); - goto jump_to_p2; - } - p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7); + VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2); + if( p->aOp[0].p1==pOp->p1 ){ + goto jump_to_p2; }else{ - if( p->aOp[0].p1==pOp->p1 ){ - VdbeBranchTaken(1, 2); - goto jump_to_p2; - } + pOp->p1 = p->aOp[0].p1; } - VdbeBranchTaken(0, 2); - pOp->p1 = p->aOp[0].p1; break; } /* Opcode: If P1 P2 P3 * * ** @@ -80671,10 +79776,11 @@ assert( p2nField ); aOffset = pC->aOffset; assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); + pCrsr = pC->uc.pCursor; if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ if( pC->eCurType==CURTYPE_PSEUDO ){ assert( pC->uc.pseudoTableReg>0 ); @@ -80686,11 +79792,10 @@ }else{ sqlite3VdbeMemSetNull(pDest); goto op_column_out; } }else{ - pCrsr = pC->uc.pCursor; assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); pC->payloadSize = sqlite3BtreePayloadSize(pCrsr); pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail); @@ -80750,11 +79855,11 @@ */ if( pC->iHdrOffsetaRow==0 ){ memset(&sMem, 0, sizeof(sMem)); - rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem); + rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem); if( rc!=SQLITE_OK ) goto abort_due_to_error; zData = (u8*)sMem.z; }else{ zData = pC->aRow; } @@ -80859,20 +79964,16 @@ /* Content is irrelevant for ** 1. the typeof() function, ** 2. the length(X) function if X is a blob, and ** 3. if the content length is zero. ** So we might as well use bogus content rather than reading - ** content from disk. - ** - ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the - ** buffer passed to it, debugging function VdbeMemPrettyPrint() may - ** read up to 16. So 16 bytes of bogus content is supplied. - */ - static u8 aZero[16]; /* This is the bogus content */ + ** content from disk. */ + static u8 aZero[8]; /* This is the bogus content */ sqlite3VdbeSerialGet(aZero, t, pDest); }else{ - rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest); + rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable, + pDest); if( rc!=SQLITE_OK ) goto abort_due_to_error; sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); pDest->flags &= ~MEM_Ephem; } } @@ -80983,24 +80084,10 @@ applyAffinity(pRec++, *(zAffinity++), encoding); assert( zAffinity[0]==0 || pRec<=pLast ); }while( zAffinity[0] ); } -#ifdef SQLITE_ENABLE_NULL_TRIM - /* NULLs can be safely trimmed from the end of the record, as long as - ** as the schema format is 2 or more and none of the omitted columns - ** have a non-NULL default value. Also, the record must be left with - ** at least one field. If P5>0 then it will be one more than the - ** index of the right-most column with a non-NULL default value */ - if( pOp->p5 ){ - while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){ - pLast--; - nField--; - } - } -#endif - /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ pRec = pLast; do{ @@ -81747,35 +80834,36 @@ assert( pOp->p2>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1); + rc = sqlite3BtreeBeginTrans(pCx->pBt, 1); } if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before ** opening it. If a transient table is required, just use the ** automatically created table with root-page 1 (an BLOB_INTKEY table). */ - if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ + if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ int pgno; assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5); + rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); assert( pKeyInfo->db==db ); assert( pKeyInfo->enc==ENC(db) ); - rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR, + pCx->pKeyInfo = pKeyInfo; + rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR, pKeyInfo, pCx->uc.pCursor); } pCx->isTable = 0; }else{ - rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR, 0, pCx->uc.pCursor); pCx->isTable = 1; } } if( rc ) goto abort_due_to_error; @@ -82003,12 +81091,11 @@ pC->seekOp = pOp->opcode; #endif if( pC->isTable ){ /* The BTREE_SEEK_EQ flag is only set on index cursors */ - assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 - || CORRUPT_DB ); + assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 ); /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so convert it. */ pIn3 = &aMem[pOp->p3]; @@ -82206,13 +81293,14 @@ int alreadyExists; int takeJump; int ii; VdbeCursor *pC; int res; - UnpackedRecord *pFree; + char *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7]; #ifdef SQLITE_TEST if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++; #endif @@ -82225,10 +81313,11 @@ #endif pIn3 = &aMem[pOp->p3]; assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->isTable==0 ); + pFree = 0; if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; r.aMem = pIn3; #ifdef SQLITE_DEBUG @@ -82237,13 +81326,14 @@ assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 ); if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]); } #endif pIdxKey = &r; - pFree = 0; }else{ - pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); + pIdxKey = sqlite3VdbeAllocUnpackedRecord( + pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree + ); if( pIdxKey==0 ) goto no_mem; assert( pIn3->flags & MEM_Blob ); (void)ExpandBlob(pIn3); sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } @@ -82259,11 +81349,11 @@ break; } } } rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res); - if( pFree ) sqlite3DbFree(db, pFree); + sqlite3DbFree(db, pFree); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->seekResult = res; alreadyExists = (res==0); @@ -82486,11 +81576,11 @@ REGISTER_TRACE(pOp->p3, pMem); sqlite3VdbeMemIntegerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ - rc = SQLITE_FULL; /* IMP: R-17817-00630 */ + rc = SQLITE_FULL; /* IMP: R-12275-61338 */ goto abort_due_to_error; } if( vu.i+1 ){ v = pMem->u.i + 1; } @@ -82538,14 +81628,19 @@ ** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is ** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set, ** then rowid is stored for subsequent return by the ** sqlite3_last_insert_rowid() function (otherwise it is unmodified). ** -** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might -** run faster by avoiding an unnecessary seek on cursor P1. However, -** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior -** seeks on the cursor or if the most recent seek used a key equal to P3. +** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of +** the last seek operation (OP_NotExists or OP_SeekRowid) was a success, +** then this +** operation will not attempt to find the appropriate row before doing +** the insert but will instead overwrite the row that the cursor is +** currently pointing to. Presumably, the prior OP_NotExists or +** OP_SeekRowid opcode +** has already positioned the cursor correctly. This is an optimization +** that boosts performance by avoiding redundant seeks. ** ** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an ** UPDATE operation. Otherwise (if the flag is clear) then this opcode ** is part of an INSERT operation. The difference is only important to ** the update hook. @@ -82586,11 +81681,11 @@ assert( memIsValid(pData) ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); - assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable ); + assert( pC->isTable ); assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC ); REGISTER_TRACE(pOp->p2, pData); if( pOp->opcode==OP_Insert ){ pKey = &aMem[pOp->p3]; @@ -82602,17 +81697,18 @@ assert( pOp->opcode==OP_InsertInt ); x.nKey = pOp->p3; } if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ + assert( pC->isTable ); assert( pC->iDb>=0 ); zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; - assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) ); + assert( HasRowid(pTab) ); op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); }else{ - pTab = 0; /* Not needed. Silence a compiler warning. */ + pTab = 0; /* Not needed. Silence a comiler warning. */ zDb = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update hook, if any */ @@ -82620,15 +81716,14 @@ && pOp->p4type==P4_TABLE && !(pOp->p5 & OPFLAG_ISUPDATE) ){ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2); } - if( pOp->p5 & OPFLAG_ISNOOP ) break; #endif if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; - if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; + if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = x.nKey; if( pData->flags & MEM_Null ){ x.pData = 0; x.nData = 0; }else{ assert( pData->flags & (MEM_Blob|MEM_Str) ); @@ -82641,11 +81736,11 @@ }else{ x.nZero = 0; } x.pKey = 0; rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult + (pOp->p5 & OPFLAG_APPEND)!=0, seekResult ); pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; /* Invoke the update-hook if required. */ @@ -82733,15 +81828,12 @@ pTab = 0; /* Not needed. Silence a compiler warning. */ } #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* Invoke the pre-update-hook if required. */ - if( db->xPreUpdateCallback && pOp->p4.pTab ){ - assert( !(opflags & OPFLAG_ISUPDATE) - || HasRowid(pTab)==0 - || (aMem[pOp->p3].flags & MEM_Int) - ); + if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){ + assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) ); sqlite3VdbePreUpdateHook(p, pC, (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, zDb, pTab, pC->movetoTarget, pOp->p3 ); @@ -82768,11 +81860,10 @@ } #endif rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5); pC->cacheStatus = CACHE_STALE; - pC->seekResult = 0; if( rc ) goto abort_due_to_error; /* Invoke the update-hook if required. */ if( opflags & OPFLAG_NCHANGE ){ p->nChange++; @@ -82855,55 +81946,54 @@ if( rc ) goto abort_due_to_error; p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE; break; } -/* Opcode: RowData P1 P2 P3 * * +/* Opcode: RowData P1 P2 * * * ** Synopsis: r[P2]=data ** -** Write into register P2 the complete row content for the row at -** which cursor P1 is currently pointing. +** Write into register P2 the complete row data for cursor P1. ** There is no interpretation of the data. ** It is just copied onto the P2 register exactly as ** it is found in the database file. ** -** If cursor P1 is an index, then the content is the key of the row. -** If cursor P2 is a table, then the content extracted is the data. +** If the P1 cursor must be pointing to a valid row (not a NULL row) +** of a real table, not a pseudo-table. +*/ +/* Opcode: RowKey P1 P2 * * * +** Synopsis: r[P2]=key +** +** Write into register P2 the complete row key for cursor P1. +** There is no interpretation of the data. +** The key is copied onto the P2 register exactly as +** it is found in the database file. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. -** -** If P3!=0 then this opcode is allowed to make an ephermeral pointer -** into the database page. That means that the content of the output -** register will be invalidated as soon as the cursor moves - including -** moves caused by other cursors that "save" the the current cursors -** position in order that they can write to the same table. If P3==0 -** then a copy of the data is made into memory. P3!=0 is faster, but -** P3==0 is safer. -** -** If P3!=0 then the content of the P2 register is unsuitable for use -** in OP_Result and any OP_Result will invalidate the P2 register content. -** The P2 register content is invalidated by opcodes like OP_Function or -** by any use of another cursor pointing to the same table. */ +case OP_RowKey: case OP_RowData: { VdbeCursor *pC; BtCursor *pCrsr; u32 n; - pOut = out2Prerelease(p, pOp); + pOut = &aMem[pOp->p2]; + memAboutToChange(p, pOut); + /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); assert( isSorter(pC)==0 ); + assert( pC->isTable || pOp->opcode!=OP_RowData ); + assert( pC->isTable==0 || pOp->opcode==OP_RowData ); assert( pC->nullRow==0 ); assert( pC->uc.pCursor!=0 ); pCrsr = pC->uc.pCursor; - /* The OP_RowData opcodes always follow OP_NotExists or + /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or ** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions ** that might invalidate the cursor. ** If this where not the case, on of the following assert()s ** would fail. Should this ever change (because of changes in the code ** generator) then the fix would be to insert a call to @@ -82919,13 +82009,22 @@ n = sqlite3BtreePayloadSize(pCrsr); if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } testcase( n==0 ); - rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut); + if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){ + goto no_mem; + } + pOut->n = n; + MemSetTypeFlag(pOut, MEM_Blob); + if( pC->isTable==0 ){ + rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z); + }else{ + rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z); + } if( rc ) goto abort_due_to_error; - if( !pOp->p3 ) Deephemeralize(pOut); + pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); REGISTER_TRACE(pOp->p2, pOut); break; } @@ -83010,17 +82109,10 @@ ** to the following instruction. ** ** This opcode leaves the cursor configured to move in reverse order, ** from the end toward the beginning. In other words, the cursor is ** configured to use Prev, not Next. -** -** If P3 is -1, then the cursor is positioned at the end of the btree -** for the purpose of appending a new entry onto the btree. In that -** case P2 must be 0. It is assumed that the cursor is used only for -** appending and so if the cursor is valid, then the cursor must already -** be pointing at the end of the btree and so no changes are made to -** the cursor. */ case OP_Last: { /* jump */ VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -83030,67 +82122,27 @@ assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; res = 0; assert( pCrsr!=0 ); + rc = sqlite3BtreeLast(pCrsr, &res); + pC->nullRow = (u8)res; + pC->deferredMoveto = 0; + pC->cacheStatus = CACHE_STALE; pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif - if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){ - rc = sqlite3BtreeLast(pCrsr, &res); - pC->nullRow = (u8)res; - pC->deferredMoveto = 0; - pC->cacheStatus = CACHE_STALE; - if( rc ) goto abort_due_to_error; - if( pOp->p2>0 ){ - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - } - }else{ - assert( pOp->p2==0 ); - } - break; -} - -/* Opcode: IfSmaller P1 P2 P3 * * -** -** Estimate the number of rows in the table P1. Jump to P2 if that -** estimate is less than approximately 2**(0.1*P3). -*/ -case OP_IfSmaller: { /* jump */ - VdbeCursor *pC; - BtCursor *pCrsr; - int res; - i64 sz; - - assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); - pCrsr = pC->uc.pCursor; - assert( pCrsr ); - rc = sqlite3BtreeFirst(pCrsr, &res); - if( rc ) goto abort_due_to_error; - if( res==0 ){ - sz = sqlite3BtreeRowCountEst(pCrsr); - if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)p3 ) res = 1; - } - VdbeBranchTaken(res!=0,2); - if( res ) goto jump_to_p2; - break; -} - - -/* Opcode: SorterSort P1 P2 * * * -** -** After all records have been inserted into the Sorter object -** identified by P1, invoke this opcode to actually do the sorting. -** Jump to P2 if there are no records to be sorted. -** -** This opcode is an alias for OP_Sort and OP_Rewind that is used -** for Sorter objects. -*/ + if( rc ) goto abort_due_to_error; + if( pOp->p2>0 ){ + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; + } + break; +} + + /* Opcode: Sort P1 P2 * * * ** ** This opcode does exactly the same thing as OP_Rewind except that ** it increments an undocumented global variable used for testing. ** @@ -83214,17 +82266,10 @@ /* Opcode: PrevIfOpen P1 P2 P3 P4 P5 ** ** This opcode works just like Prev except that if cursor P1 is not ** open it behaves a no-op. */ -/* Opcode: SorterNext P1 P2 * * P5 -** -** This opcode works just like OP_Next except that P1 must be a -** sorter object for which the OP_SorterSort opcode has been -** invoked. This opcode advances the cursor to the next sorted -** record, or jumps to P2 if there are no more sorted records. -*/ case OP_SorterNext: { /* jump */ VdbeCursor *pC; int res; pC = p->apCsr[pOp->p1]; @@ -83277,45 +82322,31 @@ pC->nullRow = 1; } goto check_for_interrupt; } -/* Opcode: IdxInsert P1 P2 P3 P4 P5 +/* Opcode: IdxInsert P1 P2 P3 * P5 ** Synopsis: key=r[P2] ** ** Register P2 holds an SQL index key made using the ** MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** -** If P4 is not zero, then it is the number of values in the unpacked -** key of reg(P2). In that case, P3 is the index of the first register -** for the unpacked key. The availability of the unpacked key can sometimes -** be an optimization. -** -** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer -** that this insert is likely to be an append. +** P3 is a flag that provides a hint to the b-tree layer that this +** insert is likely to be an append. ** ** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is ** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear, ** then the change counter is unchanged. ** -** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might -** run faster by avoiding an unnecessary seek on cursor P1. However, -** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior -** seeks on the cursor or if the most recent seek used a key equivalent -** to P2. +** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have +** just done a seek to the spot where the new entry is to be inserted. +** This flag avoids doing an extra seek. ** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ -/* Opcode: SorterInsert P1 P2 * * * -** Synopsis: key=r[P2] -** -** Register P2 holds an SQL index key made using the -** MakeRecord instructions. This opcode writes that key -** into the sorter P1. Data for the entry is nil. -*/ case OP_SorterInsert: /* in2 */ case OP_IdxInsert: { /* in2 */ VdbeCursor *pC; BtreePayload x; @@ -83333,14 +82364,11 @@ if( pOp->opcode==OP_SorterInsert ){ rc = sqlite3VdbeSorterWrite(pC, pIn2); }else{ x.nKey = pIn2->n; x.pKey = pIn2->z; - x.aMem = aMem + pOp->p3; - x.nMem = (u16)pOp->p4.i; - rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, - (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), + rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } @@ -83380,11 +82408,10 @@ rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE); if( rc ) goto abort_due_to_error; } assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; - pC->seekResult = 0; break; } /* Opcode: Seek P1 * P3 P4 * ** Synopsis: Move P3 to P1.rowid @@ -83458,10 +82485,11 @@ pTabCur->aAltMap = pOp->p4.ai; pTabCur->pAltCursor = pC; }else{ pOut = out2Prerelease(p, pOp); pOut->u.i = rowid; + pOut->flags = MEM_Int; } }else{ assert( pOp->opcode==OP_IdxRowid ); sqlite3VdbeMemSetNull(&aMem[pOp->p2]); } @@ -83721,22 +82749,10 @@ if( rc ) goto abort_due_to_error; pOut->u.i = pgno; break; } -/* Opcode: SqlExec * * * P4 * -** -** Run the SQL statement or statements specified in the P4 string. -*/ -case OP_SqlExec: { - db->nSqlExec++; - rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0); - db->nSqlExec--; - if( rc ) goto abort_due_to_error; - break; -} - /* Opcode: ParseSchema P1 * * P4 * ** ** Read and parse all entries from the SQLITE_MASTER table of database P1 ** that match the WHERE clause P4. ** @@ -83761,11 +82777,11 @@ iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); /* Used to be a conditional */ { - zMaster = MASTER_NAME; + zMaster = SCHEMA_TABLE(iDb); initData.db = db; initData.iDb = pOp->p1; initData.pzErrMsg = &p->zErrMsg; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", @@ -83853,11 +82869,11 @@ ** ** Do an analysis of the currently open database. Store in ** register P1 the text of an error message describing any problems. ** If no problems are found, store a NULL in register P1. ** -** The register P3 contains one less than the maximum number of allowed errors. +** The register P3 contains the maximum number of allowed errors. ** At most reg(P3) errors will be reported. ** In other words, the analysis stops as soon as reg(P1) errors are ** seen. Reg(P1) is updated with the number of errors remaining. ** ** The root page numbers of all tables in the database are integers @@ -83886,18 +82902,18 @@ assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); pIn1 = &aMem[pOp->p1]; assert( pOp->p5nDb ); assert( DbMaskTest(p->btreeMask, pOp->p5) ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, - (int)pnErr->u.i+1, &nErr); + (int)pnErr->u.i, &nErr); + pnErr->u.i -= nErr; sqlite3VdbeMemSetNull(pIn1); if( nErr==0 ){ assert( z==0 ); }else if( z==0 ){ goto no_mem; }else{ - pnErr->u.i -= nErr-1; sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free); } UPDATE_MAX_BLOBSIZE(pIn1); sqlite3VdbeChangeEncoding(pIn1, encoding); break; @@ -84072,12 +83088,11 @@ nMem = pProgram->nMem + pProgram->nCsr; assert( nMem>0 ); if( pProgram->nCsr==0 ) nMem++; nByte = ROUND8(sizeof(VdbeFrame)) + nMem * sizeof(Mem) - + pProgram->nCsr * sizeof(VdbeCursor*) - + (pProgram->nOp + 7)/8; + + pProgram->nCsr * sizeof(VdbeCursor *); pFrame = sqlite3DbMallocZero(db, nByte); if( !pFrame ){ goto no_mem; } sqlite3VdbeMemRelease(pRt); @@ -84112,11 +83127,11 @@ assert( (int)(pOp - aOp)==pFrame->pc ); } p->nFrame++; pFrame->pParent = p->pFrame; - pFrame->lastRowid = db->lastRowid; + pFrame->lastRowid = lastRowid; pFrame->nChange = p->nChange; pFrame->nDbChange = p->db->nChange; assert( pFrame->pAuxData==0 ); pFrame->pAuxData = p->pAuxData; p->pAuxData = 0; @@ -84124,12 +83139,10 @@ p->pFrame = pFrame; p->aMem = aMem = VdbeFrameMem(pFrame); p->nMem = pFrame->nChildMem; p->nCursor = (u16)pFrame->nChildCsr; p->apCsr = (VdbeCursor **)&aMem[p->nMem]; - pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr]; - memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8); p->aOp = aOp = pProgram->aOp; p->nOp = pProgram->nOp; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; #endif @@ -84275,61 +83288,48 @@ ** and r[P2] is set to -1. ** ** Otherwise, r[P2] is set to the sum of r[P1] and r[P3]. */ case OP_OffsetLimit: { /* in1, out2, in3 */ - i64 x; pIn1 = &aMem[pOp->p1]; pIn3 = &aMem[pOp->p3]; pOut = out2Prerelease(p, pOp); assert( pIn1->flags & MEM_Int ); assert( pIn3->flags & MEM_Int ); - x = pIn1->u.i; - if( x<=0 || sqlite3AddInt64(&x, pIn3->u.i>0?pIn3->u.i:0) ){ - /* If the LIMIT is less than or equal to zero, loop forever. This - ** is documented. But also, if the LIMIT+OFFSET exceeds 2^63 then - ** also loop forever. This is undocumented. In fact, one could argue - ** that the loop should terminate. But assuming 1 billion iterations - ** per second (far exceeding the capabilities of any current hardware) - ** it would take nearly 300 years to actually reach the limit. So - ** looping forever is a reasonable approximation. */ - pOut->u.i = -1; - }else{ - pOut->u.i = x; - } + pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0); break; } -/* Opcode: IfNotZero P1 P2 * * * -** Synopsis: if r[P1]!=0 then r[P1]--, goto P2 +/* Opcode: IfNotZero P1 P2 P3 * * +** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 ** ** Register P1 must contain an integer. If the content of register P1 is -** initially greater than zero, then decrement the value in register P1. -** If it is non-zero (negative or positive) and then also jump to P2. -** If register P1 is initially zero, leave it unchanged and fall through. +** initially nonzero, then subtract P3 from the value in register P1 and +** jump to P2. If register P1 is initially zero, leave it unchanged +** and fall through. */ case OP_IfNotZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); VdbeBranchTaken(pIn1->u.i<0, 2); if( pIn1->u.i ){ - if( pIn1->u.i>0 ) pIn1->u.i--; + pIn1->u.i -= pOp->p3; goto jump_to_p2; } break; } /* Opcode: DecrJumpZero P1 P2 * * * ** Synopsis: if (--r[P1])==0 goto P2 ** -** Register P1 must hold an integer. Decrement the value in P1 -** and jump to P2 if the new value is exactly zero. +** Register P1 must hold an integer. Decrement the value in register P1 +** then jump to P2 if the new value is exactly zero. */ case OP_DecrJumpZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); - if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--; + pIn1->u.i--; VdbeBranchTaken(pIn1->u.i==0, 2); if( pIn1->u.i==0 ) goto jump_to_p2; break; } @@ -84571,11 +83571,11 @@ /* If leaving WAL mode, close the log file. If successful, the call ** to PagerCloseWal() checkpoints and deletes the write-ahead-log ** file. An EXCLUSIVE lock may still be held on the database file ** after a successful return. */ - rc = sqlite3PagerCloseWal(pPager, db); + rc = sqlite3PagerCloseWal(pPager); if( rc==SQLITE_OK ){ sqlite3PagerSetJournalMode(pPager, eNew); } }else if( eOld==PAGER_JOURNALMODE_MEMORY ){ /* Cannot transition directly from MEMORY to WAL. Use mode OFF @@ -85055,11 +84055,11 @@ rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid); db->vtabOnConflict = vtabOnConflict; sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK && pOp->p1 ){ assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); - db->lastRowid = rowid; + db->lastRowid = lastRowid = rowid; } if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){ if( pOp->p5==OE_Ignore ){ rc = SQLITE_OK; }else{ @@ -85155,15 +84155,11 @@ char *z = sqlite3VdbeExpandSql(p, zTrace); x(db->pTraceArg, z); sqlite3_free(z); }else #endif - if( db->nVdbeExec>1 ){ - char *z = sqlite3MPrintf(db, "-- %s", zTrace); - (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z); - sqlite3DbFree(db, z); - }else{ + { (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace); } } #ifdef SQLITE_USE_FCNTL_TRACE zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); @@ -85295,10 +84291,11 @@ /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: + db->lastRowid = lastRowid; testcase( nVmStep>0 ); p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); assert( rc!=SQLITE_OK || nExtraDelete==0 || sqlite3_strlike("DELETE%",p->zSql,0)!=0 @@ -85358,13 +84355,14 @@ /* ** Valid sqlite3_blob* handles point to Incrblob structures. */ typedef struct Incrblob Incrblob; struct Incrblob { + int flags; /* Copy of "flags" passed to sqlite3_blob_open() */ int nByte; /* Size of open blob, in bytes */ int iOffset; /* Byte offset of blob in cursor data */ - u16 iCol; /* Table column this handle is open on */ + int iCol; /* Table column this handle is open on */ BtCursor *pCsr; /* Cursor pointing at blob row */ sqlite3_stmt *pStmt; /* Statement holding cursor open */ sqlite3 *db; /* The associated database */ char *zDb; /* Database name */ Table *pTab; /* Table object */ @@ -85391,31 +84389,21 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){ int rc; /* Error code */ char *zErr = 0; /* Error message */ Vdbe *v = (Vdbe *)p->pStmt; - /* Set the value of register r[1] in the SQL statement to integer iRow. - ** This is done directly as a performance optimization + /* Set the value of the SQL statements only variable to integer iRow. + ** This is done directly instead of using sqlite3_bind_int64() to avoid + ** triggering asserts related to mutexes. */ - v->aMem[1].flags = MEM_Int; - v->aMem[1].u.i = iRow; - - /* If the statement has been run before (and is paused at the OP_ResultRow) - ** then back it up to the point where it does the OP_SeekRowid. This could - ** have been down with an extra OP_Goto, but simply setting the program - ** counter is faster. */ - if( v->pc>3 ){ - v->pc = 3; - rc = sqlite3VdbeExec(v); - }else{ - rc = sqlite3_step(p->pStmt); - } + assert( v->aVar[0].flags&MEM_Int ); + v->aVar[0].u.i = iRow; + + rc = sqlite3_step(p->pStmt); if( rc==SQLITE_ROW ){ VdbeCursor *pC = v->apCsr[0]; - u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0; - testcase( pC->nHdrParsed==p->iCol ); - testcase( pC->nHdrParsed==p->iCol+1 ); + u32 type = pC->aType[p->iCol]; if( type<12 ){ zErr = sqlite3MPrintf(p->db, "cannot open value of type %s", type==0?"null": type==7?"real": "integer" ); rc = SQLITE_ERROR; @@ -85456,11 +84444,11 @@ sqlite3* db, /* The database connection */ const char *zDb, /* The attached database containing the blob */ const char *zTable, /* The table containing the blob */ const char *zColumn, /* The column containing the blob */ sqlite_int64 iRow, /* The row containing the glob */ - int wrFlag, /* True -> read/write access, false -> read-only */ + int flags, /* True -> read/write access, false -> read-only */ sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */ ){ int nAttempt = 0; int iCol; /* Index of zColumn in row-record */ int rc = SQLITE_OK; @@ -85478,11 +84466,11 @@ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif - wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ + flags = !!flags; /* flags = (flags ? 1 : 0); */ sqlite3_mutex_enter(db->mutex); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); if( !pBlob ) goto blob_open_out; @@ -85538,12 +84526,13 @@ goto blob_open_out; } /* If the value is being opened for writing, check that the ** column is not indexed, and that it is not part of a foreign key. - */ - if( wrFlag ){ + ** It is against the rules to open a column to which either of these + ** descriptions applies for writing. */ + if( flags ){ const char *zFault = 0; Index *pIdx; #ifndef SQLITE_OMIT_FOREIGN_KEY if( db->flags&SQLITE_ForeignKeys ){ /* Check that the column is not part of an FK child key definition. It @@ -85600,21 +84589,23 @@ */ static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList openBlob[] = { {OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */ {OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */ - /* blobSeekToRow() will initialize r[1] to the desired rowid */ - {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ - {OP_Column, 0, 0, 1}, /* 3 */ - {OP_ResultRow, 1, 0, 0}, /* 4 */ - {OP_Halt, 0, 0, 0}, /* 5 */ + {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */ + {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 4 */ + {OP_ResultRow, 1, 0, 0}, /* 5 */ + {OP_Goto, 0, 2, 0}, /* 6 */ + {OP_Close, 0, 0, 0}, /* 7 */ + {OP_Halt, 0, 0, 0}, /* 8 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); VdbeOp *aOp; - sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, + sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); sqlite3VdbeChangeP5(v, 1); aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn); @@ -85627,19 +84618,19 @@ #ifdef SQLITE_OMIT_SHARED_CACHE aOp[0].opcode = OP_Noop; #else aOp[0].p1 = iDb; aOp[0].p2 = pTab->tnum; - aOp[0].p3 = wrFlag; + aOp[0].p3 = flags; sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT); } if( db->mallocFailed==0 ){ #endif /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ - if( wrFlag ) aOp[1].opcode = OP_OpenWrite; + if( flags ) aOp[1].opcode = OP_OpenWrite; aOp[1].p2 = pTab->tnum; aOp[1].p3 = iDb; /* Configure the number of columns. Configure the cursor to ** think that the table has one more column than it really @@ -85648,25 +84639,27 @@ ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ aOp[1].p4type = P4_INT32; aOp[1].p4.i = pTab->nCol+1; - aOp[3].p2 = pTab->nCol; + aOp[4].p2 = pTab->nCol; - pParse->nVar = 0; + pParse->nVar = 1; pParse->nMem = 1; pParse->nTab = 1; sqlite3VdbeMakeReady(v, pParse); } } + pBlob->flags = flags; pBlob->iCol = iCol; pBlob->db = db; sqlite3BtreeLeaveAll(db); if( db->mallocFailed ){ goto blob_open_out; } + sqlite3_bind_int64(pBlob->pStmt, 1, iRow); rc = blobSeekToRow(pBlob, iRow, &zErr); } while( (++nAttempt)mallocFailed==0 ){ @@ -85780,11 +84773,11 @@ /* ** Read data from a blob handle. */ SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){ - return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked); + return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData); } /* ** Write data to a blob handle. */ @@ -86806,11 +85799,11 @@ if( nWorker>=SORTER_MAX_MERGE_COUNT ){ nWorker = SORTER_MAX_MERGE_COUNT-1; } #endif - assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); + assert( pCsr->pKeyInfo && pCsr->pBt==0 ); assert( pCsr->eCurType==CURTYPE_SORTER ); szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*); sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo); @@ -87174,12 +86167,16 @@ ** structure at pTask->pUnpacked. Return SQLITE_OK if successful (or ** if no allocation was required), or SQLITE_NOMEM otherwise. */ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pTask->pUnpacked==0 ){ - pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo); - if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT; + char *pFree; + pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord( + pTask->pSorter->pKeyInfo, 0, 0, &pFree + ); + assert( pTask->pUnpacked==(UnpackedRecord*)pFree ); + if( pFree==0 ) return SQLITE_NOMEM_BKPT; pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; } return SQLITE_OK; } @@ -88576,11 +87573,13 @@ assert( pCsr->eCurType==CURTYPE_SORTER ); pSorter = pCsr->uc.pSorter; r2 = pSorter->pUnpacked; pKeyInfo = pCsr->pKeyInfo; if( r2==0 ){ - r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo); + char *p; + r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p); + assert( pSorter->pUnpacked==(UnpackedRecord*)p ); if( r2==0 ) return SQLITE_NOMEM_BKPT; r2->nField = nKeyCol; } assert( r2->nField==nKeyCol ); @@ -89047,15 +88046,15 @@ ** The return value from the callback should be one of the WRC_* ** constants to specify how to proceed with the walk. ** ** WRC_Continue Continue descending down the tree. ** -** WRC_Prune Do not descend into child nodes, but allow +** WRC_Prune Do not descend into child nodes. But allow ** the walk to continue with sibling nodes. ** ** WRC_Abort Do no more callbacks. Unwind the stack and -** return from the top-level walk call. +** return the top-level walk call. ** ** The return value from this routine is WRC_Abort to abandon the tree walk ** and WRC_Continue to continue. */ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){ @@ -89199,10 +88198,12 @@ ** This file contains routines used for walking the parser tree and ** resolve all identifiers by associating them with a particular ** table and column. */ /* #include "sqliteInt.h" */ +/* #include */ +/* #include */ /* ** Walk the expression tree pExpr and increase the aggregate function ** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node. ** This needs to occur when copying a TK_AGG_FUNCTION node from an @@ -89413,12 +88414,11 @@ } } } /* Start at the inner-most context and move outward until a match is found */ - assert( pNC && cnt==0 ); - do{ + while( pNC && cnt==0 ){ ExprList *pEList; SrcList *pSrcList = pNC->pSrcList; if( pSrcList ){ for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ @@ -89583,14 +88583,10 @@ pOrig = pEList->a[j].pExpr; if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } - if( sqlite3ExprVectorSize(pOrig)!=1 ){ - sqlite3ErrorMsg(pParse, "row value misused"); - return WRC_Abort; - } resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); cnt = 1; pMatch = 0; assert( zTab==0 && zDb==0 ); goto lookupname_end; @@ -89599,15 +88595,15 @@ } /* Advance to the next name context. The loop will exit when either ** we have a match (cnt>0) or when we run out of name contexts. */ - if( cnt ) break; - pNC = pNC->pNext; - nSubquery++; - }while( pNC ); - + if( cnt==0 ){ + pNC = pNC->pNext; + nSubquery++; + } + } /* ** If X and Y are NULL (in other words if only the column name Z is ** supplied) and the value of Z is enclosed in double-quotes, then ** Z is a string literal if it doesn't match any column names. In that @@ -89793,42 +88789,37 @@ break; } #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ - /* A column name: ID - ** Or table name and column name: ID.ID + /* A lone identifier is the name of a column. + */ + case TK_ID: { + return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); + } + + /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID - ** - ** The TK_ID and TK_OUT cases are combined so that there will only - ** be one call to lookupName(). Then the compiler will in-line - ** lookupName() for a size reduction and performance increase. */ - case TK_ID: case TK_DOT: { const char *zColumn; const char *zTable; const char *zDb; Expr *pRight; - if( pExpr->op==TK_ID ){ - zDb = 0; - zTable = 0; - zColumn = pExpr->u.zToken; - }else{ - notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); - pRight = pExpr->pRight; - if( pRight->op==TK_ID ){ - zDb = 0; - zTable = pExpr->pLeft->u.zToken; - zColumn = pRight->u.zToken; - }else{ - assert( pRight->op==TK_DOT ); - zDb = pExpr->pLeft->u.zToken; - zTable = pRight->pLeft->u.zToken; - zColumn = pRight->pRight->u.zToken; - } + /* if( pSrcList==0 ) break; */ + notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + zDb = 0; + zTable = pExpr->pLeft->u.zToken; + zColumn = pRight->u.zToken; + }else{ + assert( pRight->op==TK_DOT ); + zDb = pExpr->pLeft->u.zToken; + zTable = pRight->pLeft->u.zToken; + zColumn = pRight->pRight->u.zToken; } return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); } /* Resolve function names @@ -89968,11 +88959,10 @@ } case TK_VARIABLE: { notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } - case TK_BETWEEN: case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: @@ -89979,31 +88969,23 @@ case TK_GE: case TK_IS: case TK_ISNOT: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; + assert( pExpr->pRight!=0 ); assert( pExpr->pLeft!=0 ); nLeft = sqlite3ExprVectorSize(pExpr->pLeft); - if( pExpr->op==TK_BETWEEN ){ - nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr); - if( nRight==nLeft ){ - nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr); - } - }else{ - assert( pExpr->pRight!=0 ); - nRight = sqlite3ExprVectorSize(pExpr->pRight); - } + nRight = sqlite3ExprVectorSize(pExpr->pRight); if( nLeft!=nRight ){ testcase( pExpr->op==TK_EQ ); testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); - testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); } break; } } @@ -90963,11 +89945,11 @@ aff = sqlite3ExprAffinity(pExpr->pLeft); if( pExpr->pRight ){ aff = sqlite3CompareAffinity(pExpr->pRight, aff); }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); - }else if( aff==0 ){ + }else if( NEVER(aff==0) ){ aff = SQLITE_AFF_BLOB; } return aff; } @@ -91146,14 +90128,13 @@ Expr *pRet; if( pVector->op==TK_SELECT ){ assert( pVector->flags & EP_xIsSelect ); /* The TK_SELECT_COLUMN Expr node: ** - ** pLeft: pVector containing TK_SELECT. Not deleted. + ** pLeft: pVector containing TK_SELECT ** pRight: not used. But recursively deleted. ** iColumn: Index of a column in pVector - ** iTable: 0 or the number of columns on the LHS of an assignment ** pLeft->iTable: First in an array of register holding result, or 0 ** if the result is not yet computed. ** ** sqlite3ExprDelete() specifically skips the recursive delete of ** pLeft on TK_SELECT_COLUMN nodes. But pRight is followed, so pVector @@ -91160,11 +90141,11 @@ ** can be attached to pRight to cause this node to take ownership of ** pVector. Typically there will be multiple TK_SELECT_COLUMN nodes ** with the same pLeft pointer to the pVector, but only one of them ** will own the pVector. */ - pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0); + pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0, 0); if( pRet ){ pRet->iColumn = iField; pRet->pLeft = pVector; } assert( pRet==0 || pRet->iTable==0 ); @@ -91260,14 +90241,11 @@ int regLeft = 0; int regRight = 0; u8 opx = op; int addrDone = sqlite3VdbeMakeLabel(v); - if( nLeft!=sqlite3ExprVectorSize(pRight) ){ - sqlite3ErrorMsg(pParse, "row value misused"); - return; - } + assert( nLeft==sqlite3ExprVectorSize(pRight) ); assert( pExpr->op==TK_EQ || pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT || pExpr->op==TK_LT || pExpr->op==TK_GT || pExpr->op==TK_LE || pExpr->op==TK_GE ); @@ -91555,23 +90533,19 @@ */ SQLITE_PRIVATE Expr *sqlite3PExpr( Parse *pParse, /* Parsing context */ int op, /* Expression opcode */ Expr *pLeft, /* Left operand */ - Expr *pRight /* Right operand */ + Expr *pRight, /* Right operand */ + const Token *pToken /* Argument token */ ){ Expr *p; if( op==TK_AND && pParse->nErr==0 ){ /* Take advantage of short-circuit false optimization for AND */ p = sqlite3ExprAnd(pParse->db, pLeft, pRight); }else{ - p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); - if( p ){ - memset(p, 0, sizeof(Expr)); - p->op = op & TKFLG_MASK; - p->iAgg = -1; - } + p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1); sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); } if( p ) { sqlite3ExprCheckHeight(pParse, p->nHeight); } @@ -91670,11 +90644,11 @@ ** ** Wildcards consisting of a single "?" are assigned the next sequential ** variable number. ** ** Wildcards of the form "?nnn" are assigned the number "nnn". We make -** sure "nnn" is not too big to avoid a denial of service attack when +** sure "nnn" is not too be to avoid a denial of service attack when ** the SQL statement comes from an external source. ** ** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number ** as the previous instance of the same wildcard. Or if this is the first ** instance of the wildcard, the next sequential variable number is @@ -91681,11 +90655,10 @@ ** assigned. */ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){ sqlite3 *db = pParse->db; const char *z; - ynVar x; if( pExpr==0 ) return; assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); z = pExpr->u.zToken; assert( z!=0 ); @@ -91692,57 +90665,62 @@ assert( z[0]!=0 ); assert( n==sqlite3Strlen30(z) ); if( z[1]==0 ){ /* Wildcard of the form "?". Assign the next variable number */ assert( z[0]=='?' ); - x = (ynVar)(++pParse->nVar); + pExpr->iColumn = (ynVar)(++pParse->nVar); }else{ - int doAdd = 0; + ynVar x; if( z[0]=='?' ){ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and ** use it as the variable number */ i64 i; - int bOk; - if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/ - i = z[1]-'0'; /* The common case of ?N for a single digit N */ - bOk = 1; - }else{ - bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); - } + int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8); + x = (ynVar)i; testcase( i==0 ); testcase( i==1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); return; } - x = (ynVar)i; - if( x>pParse->nVar ){ - pParse->nVar = (int)x; - doAdd = 1; - }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){ - doAdd = 1; + if( i>pParse->nVar ){ + pParse->nVar = (int)i; } }else{ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable ** number as the prior appearance of the same name, or if the name ** has never appeared before, reuse the same variable number */ - x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n); - if( x==0 ){ - x = (ynVar)(++pParse->nVar); - doAdd = 1; - } - } - if( doAdd ){ - pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x); - } - } - pExpr->iColumn = x; - if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ + ynVar i; + for(i=x=0; inzVar; i++){ + if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){ + x = (ynVar)i+1; + break; + } + } + if( x==0 ) x = (ynVar)(++pParse->nVar); + } + pExpr->iColumn = x; + if( x>pParse->nzVar ){ + char **a; + a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0])); + if( a==0 ){ + assert( db->mallocFailed ); /* Error reported through mallocFailed */ + return; + } + pParse->azVar = a; + memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0])); + pParse->nzVar = x; + } + if( pParse->azVar[x-1]==0 ){ + pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n); + } + } + if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); } } /* @@ -91827,11 +90805,11 @@ static int dupedExprStructSize(Expr *p, int flags){ int nSize; assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ assert( EXPR_FULLSIZE<=0xfff ); assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); - if( 0==flags || p->op==TK_SELECT_COLUMN ){ + if( 0==flags ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( !ExprHasProperty(p, EP_MemToken) ); @@ -91970,12 +90948,10 @@ } }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; - assert( p->iColumn==0 || p->pRight==0 ); - assert( p->pRight==0 || p->pRight==p->pLeft ); }else{ pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0); } pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } @@ -92034,11 +91010,10 @@ } SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ ExprList *pNew; struct ExprList_item *pItem, *pOldItem; int i; - Expr *pPriorSelectCol = 0; assert( db!=0 ); if( p==0 ) return 0; pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nExpr = i = p->nExpr; @@ -92049,28 +91024,11 @@ return 0; } pOldItem = p->a; for(i=0; inExpr; i++, pItem++, pOldItem++){ Expr *pOldExpr = pOldItem->pExpr; - Expr *pNewExpr; pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags); - if( pOldExpr - && pOldExpr->op==TK_SELECT_COLUMN - && (pNewExpr = pItem->pExpr)!=0 - ){ - assert( pNewExpr->iColumn==0 || i>0 ); - if( pNewExpr->iColumn==0 ){ - assert( pOldExpr->pLeft==pOldExpr->pRight ); - pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight; - }else{ - assert( i>0 ); - assert( pItem[-1].pExpr!=0 ); - assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 ); - assert( pPriorSelectCol==pItem[-1].pExpr->pLeft ); - pNewExpr->pLeft = pPriorSelectCol; - } - } pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); pItem->sortOrder = pOldItem->sortOrder; pItem->done = 0; pItem->bSpanIsTab = pOldItem->bSpanIsTab; @@ -92117,11 +91075,11 @@ pNewItem->u1.pFuncArg = sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); } pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ - pTab->nTabRef++; + pTab->nRef++; } pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); pNewItem->colUsed = pOldItem->colUsed; @@ -92150,45 +91108,37 @@ pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->idx = pOldItem->idx; } return pNew; } -SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){ - Select *pRet = 0; - Select *pNext = 0; - Select **pp = &pRet; - Select *p; - +SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ + Select *pNew, *pPrior; assert( db!=0 ); - for(p=pDup; p; p=p->pPrior){ - Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); - if( pNew==0 ) break; - pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); - pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); - pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); - pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); - pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags); - pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags); - pNew->op = p->op; - pNew->pNext = pNext; - pNew->pPrior = 0; - pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); - pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags); - pNew->iLimit = 0; - pNew->iOffset = 0; - pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; - pNew->addrOpenEphm[0] = -1; - pNew->addrOpenEphm[1] = -1; - pNew->nSelectRow = p->nSelectRow; - pNew->pWith = withDup(db, p->pWith); - sqlite3SelectSetName(pNew, p->zSelName); - *pp = pNew; - pp = &pNew->pPrior; - pNext = pNew; - } - - return pRet; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRawNN(db, sizeof(*p) ); + if( pNew==0 ) return 0; + pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags); + pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags); + pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags); + pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags); + pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags); + pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags); + pNew->op = p->op; + pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags); + if( pPrior ) pPrior->pNext = pNew; + pNew->pNext = 0; + pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); + pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags); + pNew->iLimit = 0; + pNew->iOffset = 0; + pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->nSelectRow = p->nSelectRow; + pNew->pWith = withDup(db, p->pWith); + sqlite3SelectSetName(pNew, p->zSelName); + return pNew; } #else SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ assert( p==0 ); return 0; @@ -92249,11 +91199,11 @@ ** ** (a,b,c) = (expr1,expr2,expr3) ** Or: (a,b,c) = (SELECT x,y,z FROM ....) ** ** For each term of the vector assignment, append new entries to the -** expression list pList. In the case of a subquery on the RHS, append +** expression list pList. In the case of a subquery on the LHS, append ** TK_SELECT_COLUMN expressions. */ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to append. Might be NULL */ @@ -92266,45 +91216,30 @@ int iFirst = pList ? pList->nExpr : 0; /* pColumns can only be NULL due to an OOM but an OOM will cause an ** exit prior to this routine being invoked */ if( NEVER(pColumns==0) ) goto vector_append_error; if( pExpr==0 ) goto vector_append_error; - - /* If the RHS is a vector, then we can immediately check to see that - ** the size of the RHS and LHS match. But if the RHS is a SELECT, - ** wildcards ("*") in the result set of the SELECT must be expanded before - ** we can do the size check, so defer the size check until code generation. - */ - if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){ + n = sqlite3ExprVectorSize(pExpr); + if( pColumns->nId!=n ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pColumns->nId, n); goto vector_append_error; } - - for(i=0; inId; i++){ + for(i=0; inExpr==iFirst+i+1 ); pList->a[pList->nExpr-1].zName = pColumns->a[i].zName; pColumns->a[i].zName = 0; } } - if( pExpr->op==TK_SELECT ){ if( pList && pList->a[iFirst].pExpr ){ - Expr *pFirst = pList->a[iFirst].pExpr; - assert( pFirst->op==TK_SELECT_COLUMN ); - - /* Store the SELECT statement in pRight so it will be deleted when - ** sqlite3ExprListDelete() is called */ - pFirst->pRight = pExpr; + assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN ); + pList->a[iFirst].pExpr->pRight = pExpr; pExpr = 0; - - /* Remember the size of the LHS in iTable so that we can check that - ** the RHS and LHS sizes match during code generation. */ - pFirst->iTable = pColumns->nId; } } vector_append_error: sqlite3ExprDelete(db, pExpr); @@ -92592,11 +91527,10 @@ ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; - if( p==0 ) return 0; /* Can only happen following on OOM */ /* If an expression is an integer literal that fits in a signed 32-bit ** integer, then the EP_IntValue flag will have already been set */ assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0 || sqlite3GetInt32(p->u.zToken, &rc)==0 ); @@ -93100,11 +92034,11 @@ int nVal = sqlite3ExprVectorSize(pLeft); Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0; char *zRet; assert( pExpr->op==TK_IN ); - zRet = sqlite3DbMallocRaw(pParse->db, nVal+1); + zRet = sqlite3DbMallocZero(pParse->db, nVal+1); if( zRet ){ int i; for(i=0; iflags & EP_xIsSelect ){ - sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1); - }else -#endif - { - sqlite3ErrorMsg(pParse, "row value misused"); - } -} - /* ** Generate code for scalar subqueries used as a subquery expression, EXISTS, ** or IN operators. Examples: ** ** (SELECT a FROM b) -- subquery @@ -93265,10 +92177,11 @@ if( ALWAYS(pEList->nExpr==nVal) ){ SelectDest dest; int i; sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.zAffSdst = exprINAffinity(pParse, pExpr); + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); pSelect->iLimit = 0; testcase( pSelect->selFlags & SF_Distinct ); testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */ if( sqlite3Select(pParse, pSelect, &dest) ){ sqlite3DbFree(pParse->db, dest.zAffSdst); @@ -93339,11 +92252,11 @@ VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3); }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); sqlite3ExprCacheAffinityChange(pParse, r3, 1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); } } } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); @@ -93434,11 +92347,15 @@ if( nVector!=pIn->x.pSelect->pEList->nExpr ){ sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector); return 1; } }else if( nVector!=1 ){ - sqlite3VectorErrorMsg(pParse, pIn->pLeft); + if( (pIn->pLeft->flags & EP_xIsSelect) ){ + sqlite3SubselectError(pParse, nVector, 1); + }else{ + sqlite3ErrorMsg(pParse, "row value misused"); + } return 1; } return 0; } #endif @@ -93739,26 +92656,26 @@ int c; i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); c = sqlite3DecOrHexToI64(z, &value); - if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){ + if( c==0 || (c==2 && negFlag) ){ + if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } + sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); + }else{ #ifdef SQLITE_OMIT_FLOATING_POINT sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); #else #ifndef SQLITE_OMIT_HEX_INTEGER if( sqlite3_strnicmp(z,"0x",2)==0 ){ - sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z); + sqlite3ErrorMsg(pParse, "hex literal too big: %s", z); }else #endif { codeReal(v, z, negFlag, iMem); } #endif - }else{ - if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } - sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); } } } /* @@ -94004,11 +92921,11 @@ ** Clear all column cache entries. */ SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){ int i; -#ifdef SQLITE_DEBUG +#if SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("CLEAR\n"); } #endif for(i=0; inColCache; i++){ @@ -94093,11 +93010,11 @@ }else{ int i; iResult = pParse->nMem+1; pParse->nMem += nResult; for(i=0; ix.pList->a[i].pExpr, i+iResult); + sqlite3ExprCode(pParse, p->x.pList->a[i].pExpr, i+iResult); } } } return iResult; } @@ -94205,14 +93122,13 @@ assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( pExpr->u.zToken!=0 ); assert( pExpr->u.zToken[0]!=0 ); sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target); if( pExpr->u.zToken[1]!=0 ){ - const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn); - assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 ); - pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */ - sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC); + assert( pExpr->u.zToken[0]=='?' + || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 ); + sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC); } return target; } case TK_REGISTER: { return pExpr->iTable; @@ -94358,15 +93274,10 @@ int i; /* Loop counter */ sqlite3 *db = pParse->db; /* The database connection */ u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ - if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){ - /* SQL functions can be expensive. So try to move constant functions - ** out of the inner loop, even if that means an extra OP_Copy. */ - return sqlite3ExprCodeAtInit(pParse, pExpr, -1); - } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( ExprHasProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; }else{ pFarg = pExpr->x.pList; @@ -94411,26 +93322,10 @@ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); } -#ifdef SQLITE_DEBUG - /* The AFFINITY() function evaluates to a string that describes - ** the type affinity of the argument. This is used for testing of - ** the SQLite type logic. - */ - if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){ - const char *azAff[] = { "blob", "text", "numeric", "integer", "real" }; - char aff; - assert( nFarg==1 ); - aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); - sqlite3VdbeLoadString(v, target, - aff ? azAff[aff-SQLITE_AFF_BLOB] : "none"); - return target; - } -#endif - for(i=0; ia[i].pExpr) ){ testcase( i==31 ); constMask |= MASKBIT32(i); } @@ -94515,21 +93410,13 @@ return sqlite3CodeSubselect(pParse, pExpr, 0, 0); } break; } case TK_SELECT_COLUMN: { - int n; if( pExpr->pLeft->iTable==0 ){ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0); } - assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT ); - if( pExpr->iTable - && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) - ){ - sqlite3ErrorMsg(pParse, "%d columns assigned %d values", - pExpr->iTable, n); - } return pExpr->pLeft->iTable + pExpr->iColumn; } case TK_IN: { int destIfFalse = sqlite3VdbeMakeLabel(v); int destIfNull = sqlite3VdbeMakeLabel(v); @@ -94743,44 +93630,28 @@ return inReg; } /* ** Factor out the code of the given expression to initialization time. -** -** If regDest>=0 then the result is always stored in that register and the -** result is not reusable. If regDest<0 then this routine is free to -** store the value whereever it wants. The register where the expression -** is stored is returned. When regDest<0, two identical expressions will -** code to the same register. */ -SQLITE_PRIVATE int sqlite3ExprCodeAtInit( +SQLITE_PRIVATE void sqlite3ExprCodeAtInit( Parse *pParse, /* Parsing context */ Expr *pExpr, /* The expression to code when the VDBE initializes */ - int regDest /* Store the value in this register */ + int regDest, /* Store the value in this register */ + u8 reusable /* True if this expression is reusable */ ){ ExprList *p; assert( ConstFactorOk(pParse) ); p = pParse->pConstExpr; - if( regDest<0 && p ){ - struct ExprList_item *pItem; - int i; - for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ - if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){ - return pItem->u.iConstExprReg; - } - } - } pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); p = sqlite3ExprListAppend(pParse, p, pExpr); if( p ){ struct ExprList_item *pItem = &p->a[p->nExpr-1]; - pItem->reusable = regDest<0; - if( regDest<0 ) regDest = ++pParse->nMem; pItem->u.iConstExprReg = regDest; + pItem->reusable = reusable; } pParse->pConstExpr = p; - return regDest; } /* ** Generate code to evaluate an expression and store the results ** into a register. Return the register number where the results @@ -94799,12 +93670,23 @@ pExpr = sqlite3ExprSkipCollate(pExpr); if( ConstFactorOk(pParse) && pExpr->op!=TK_REGISTER && sqlite3ExprIsConstantNotJoin(pExpr) ){ + ExprList *p = pParse->pConstExpr; + int i; *pReg = 0; - r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1); + if( p ){ + struct ExprList_item *pItem; + for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ + if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){ + return pItem->u.iConstExprReg; + } + } + } + r2 = ++pParse->nMem; + sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1); }else{ int r1 = sqlite3GetTempReg(pParse); r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( r2==r1 ){ *pReg = r1; @@ -94854,11 +93736,11 @@ ** in register target. If the expression is constant, then this routine ** might choose to code the expression at initialization time. */ SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){ if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){ - sqlite3ExprCodeAtInit(pParse, pExpr, target); + sqlite3ExprCodeAtInit(pParse, pExpr, target, 0); }else{ sqlite3ExprCode(pParse, pExpr, target); } } @@ -94918,19 +93800,14 @@ assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; ipExpr; - if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){ - if( flags & SQLITE_ECEL_OMITREF ){ - i--; - n--; - }else{ - sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); - } + if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){ + sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ - sqlite3ExprCodeAtInit(pParse, pExpr, target+i); + sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); }else{ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); if( inReg!=target+i ){ VdbeOp *pOp; if( copyOp==OP_Copy @@ -94999,15 +93876,10 @@ compRight.pRight = pExpr->x.pList->a[1].pExpr; exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1)); if( xJump ){ xJump(pParse, &exprAnd, dest, jumpIfNull); }else{ - /* Mark the expression is being from the ON or USING clause of a join - ** so that the sqlite3ExprCodeTarget() routine will not attempt to move - ** it into the Parse.pConstExpr list. We should use a new bit for this, - ** for clarity, but we are out of bits in the Expr.flags field so we - ** have to reuse the EP_FromJoin bit. Bummer. */ exprX.flags |= EP_FromJoin; sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } sqlite3ReleaseTempReg(pParse, regFree1); @@ -95412,21 +94284,10 @@ if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; } return 0; } -/* -** Like sqlite3ExprCompare() except COLLATE operators at the top-level -** are ignored. -*/ -SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ - return sqlite3ExprCompare( - sqlite3ExprSkipCollate(pA), - sqlite3ExprSkipCollate(pB), - iTab); -} - /* ** Return true if we can prove the pE2 will always be true if pE1 is ** true. Return false if we cannot complete the proof or if pE2 might ** be false. Examples: ** @@ -95453,14 +94314,15 @@ && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) ){ return 1; } - if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ - Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); - testcase( pX!=pE1->pLeft ); - if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; + if( pE2->op==TK_NOTNULL + && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0 + && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS) + ){ + return 1; } return 0; } /* @@ -96378,11 +95240,11 @@ ** for which the renamed table is the parent table. */ if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = sqlite_rename_parent(sql, %Q, %Q) " - "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere); + "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere); sqlite3DbFree(db, zWhere); } } #endif @@ -96402,11 +95264,11 @@ "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " "'sqlite_autoindex_' || %Q || substr(name,%d+18) " "ELSE name END " "WHERE tbl_name=%Q COLLATE nocase AND " "(type='table' OR type='index' OR type='trigger');", - zDb, MASTER_NAME, zName, zName, zName, + zDb, SCHEMA_TABLE(iDb), zName, zName, zName, #ifndef SQLITE_OMIT_TRIGGER zName, #endif zName, nTabName, zTabName ); @@ -96563,11 +95425,11 @@ db->flags |= SQLITE_PreferBuiltin; sqlite3NestedParse(pParse, "UPDATE \"%w\".%s SET " "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " "WHERE type = 'table' AND name = %Q", - zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1, + zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, zTab ); sqlite3DbFree(db, zCol); db->flags = savedDbFlags; } @@ -96647,11 +95509,11 @@ ** prefix on their name. */ pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); if( !pNew ) goto exit_begin_add_column; pParse->pNewTable = pNew; - pNew->nTabRef = 1; + pNew->nRef = 1; pNew->nCol = pTab->nCol; assert( pNew->nCol>0 ); nAlloc = (((pNew->nCol-1)/8)*8)+8; assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); @@ -96667,11 +95529,11 @@ pCol->zColl = 0; pCol->pDflt = 0; } pNew->pSchema = db->aDb[iDb].pSchema; pNew->addColOffset = pTab->addColOffset; - pNew->nTabRef = 1; + pNew->nRef = 1; /* Begin a transaction and increment the schema cookie. */ sqlite3BeginWriteOperation(pParse, 0, iDb); v = sqlite3GetVdbe(pParse); if( !v ) goto exit_begin_add_column; @@ -96975,11 +95837,10 @@ Stat4Sample current; /* Current row as a Stat4Sample */ u32 iPrn; /* Pseudo-random number used for sampling */ Stat4Sample *aBest; /* Array of nCol best samples */ int iMin; /* Index in a[] of entry with minimum score */ int nSample; /* Current number of samples */ - int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */ int iGet; /* Index of current sample accessed by stat_get() */ Stat4Sample *a; /* Array of mxSample Stat4Sample objects */ sqlite3 *db; /* Database connection, for malloc() */ }; @@ -97240,17 +96101,10 @@ int i; assert( IsStat4 || nEqZero==0 ); #ifdef SQLITE_ENABLE_STAT4 - /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0 - ** values in the anEq[] array of any sample in Stat4Accum.a[]. In - ** other words, if nMaxEqZero is n, then it is guaranteed that there - ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */ - if( nEqZero>p->nMaxEqZero ){ - p->nMaxEqZero = nEqZero; - } if( pNew->isPSample==0 ){ Stat4Sample *pUpgrade = 0; assert( pNew->anEq[pNew->iCol]>0 ); /* This sample is being added because the prefix that ends in column @@ -97344,26 +96198,16 @@ if( p->nSamplemxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ sampleInsert(p, pBest, i); } } - /* Check that no sample contains an anEq[] entry with an index of - ** p->nMaxEqZero or greater set to zero. */ - for(i=p->nSample-1; i>=0; i--){ - int j; - for(j=p->nMaxEqZero; jnCol; j++) assert( p->a[i].anEq[j]>0 ); - } - - /* Update the anEq[] fields of any samples already collected. */ - if( iChngnMaxEqZero ){ - for(i=p->nSample-1; i>=0; i--){ - int j; - for(j=iChng; jnCol; j++){ - if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; - } - } - p->nMaxEqZero = iChng; + /* Update the anEq[] fields of any samples already collected. */ + for(i=p->nSample-1; i>=0; i--){ + int j; + for(j=iChng; jnCol; j++){ + if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j]; + } } #endif #if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4) if( iChng==0 ){ @@ -97500,16 +96344,10 @@ ** the Stat4Accum object by prior calls to stat_push(). The P parameter ** has type BLOB but it is really just a pointer to the Stat4Accum object. ** The content to returned is determined by the parameter J ** which is one of the STAT_GET_xxxx values defined above. ** -** The stat_get(P,J) function is not available to generic SQL. It is -** inserted as part of a manually constructed bytecode program. (See -** the callStatGet() routine below.) It is guaranteed that the P -** parameter will always be a poiner to a Stat4Accum object, never a -** NULL. -** ** If neither STAT3 nor STAT4 are enabled, then J is always ** STAT_GET_STAT1 and is hence omitted and this routine becomes ** a one-parameter function, stat_get(P), that always returns the ** stat1 table entry information. */ @@ -97889,11 +96727,11 @@ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable); int j, k, regKey; regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol); for(j=0; jnKeyCol; j++){ k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]); - assert( k>=0 && knColumn ); + assert( k>=0 && knCol ); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j); VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName)); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid); sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol); @@ -98073,32 +96911,44 @@ /* Form 1: Analyze everything */ for(i=0; inDb; i++){ if( i==1 ) continue; /* Do not analyze the TEMP database */ analyzeDatabase(pParse, i); } - }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){ - /* Analyze the schema named as the argument */ - analyzeDatabase(pParse, iDb); + }else if( pName2->n==0 ){ + /* Form 2: Analyze the database or table named */ + iDb = sqlite3FindDb(db, pName1); + if( iDb>=0 ){ + analyzeDatabase(pParse, iDb); + }else{ + z = sqlite3NameFromToken(db, pName1); + if( z ){ + if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){ + analyzeTable(pParse, pIdx->pTable, pIdx); + }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){ + analyzeTable(pParse, pTab, 0); + } + sqlite3DbFree(db, z); + } + } }else{ - /* Form 3: Analyze the table or index named as an argument */ + /* Form 3: Analyze the fully qualified table name */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ - zDb = pName2->n ? db->aDb[iDb].zDbSName : 0; + zDb = db->aDb[iDb].zDbSName; z = sqlite3NameFromToken(db, pTableName); if( z ){ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ analyzeTable(pParse, pIdx->pTable, pIdx); }else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){ analyzeTable(pParse, pTab, 0); } sqlite3DbFree(db, z); } - } + } } - if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){ - sqlite3VdbeAddOp0(v, OP_Expire); - } + v = sqlite3GetVdbe(pParse); + if( v ) sqlite3VdbeAddOp0(v, OP_Expire); } /* ** Used to pass information from the analyzer reader through to the ** callback routine. @@ -98223,24 +97073,19 @@ } aiRowEst = pIndex->aiRowEst; #endif pIndex->bUnordered = 0; decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); - pIndex->hasStat1 = 1; - if( pIndex->pPartIdxWhere==0 ){ - pTable->nRowLogEst = pIndex->aiRowLogEst[0]; - pTable->tabFlags |= TF_HasStat1; - } + if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0]; }else{ Index fakeIdx; fakeIdx.szIdxRow = pTable->szTabRow; #ifdef SQLITE_ENABLE_COSTMULT fakeIdx.pTable = pTable; #endif decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx); pTable->szTabRow = fakeIdx.szIdxRow; - pTable->tabFlags |= TF_HasStat1; } return 0; } @@ -98317,11 +97162,11 @@ sumEq += aSample[i].anEq[iCol]; nSum100 += 100; } } - if( nDist100>nSum100 && sumEqnSum100 ){ avgEq = ((i64)100 * (nRow - sumEq))/(nDist100 - nSum100); } if( avgEq==0 ) avgEq = 1; pIdx->aAvgEq[iCol] = avgEq; } @@ -98468,13 +97313,11 @@ pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); if( pSample->p==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM_BKPT; } - if( pSample->n ){ - memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); - } + memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); pIdx->nSample++; } rc = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ) initAvgEq(pPrevIdx); return rc; @@ -98531,24 +97374,19 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ analysisInfo sInfo; HashElem *i; char *zSql; int rc = SQLITE_OK; - Schema *pSchema = db->aDb[iDb].pSchema; assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); /* Clear any prior statistics */ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){ - Table *pTab = sqliteHashData(i); - pTab->tabFlags &= ~TF_HasStat1; - } - for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); - pIdx->hasStat1 = 0; + pIdx->aiRowLogEst[0] = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3DeleteIndexSamples(db, pIdx); pIdx->aSample = 0; #endif } @@ -98567,23 +97405,23 @@ } } /* Set appropriate defaults on all indexes not in the sqlite_stat1 table */ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); - if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx); + if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx); } /* Load the statistics from the sqlite_stat4 table. */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){ db->lookaside.bDisable++; rc = loadStat4(db, sInfo.zDatabase); db->lookaside.bDisable--; } - for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); sqlite3_free(pIdx->aiRowEst); pIdx->aiRowEst = 0; } #endif @@ -98736,11 +97574,10 @@ assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags); sqlite3_free( zPath ); db->nDb++; - db->skipBtreeMutex = 0; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; zErrDyn = sqlite3MPrintf(db, "database is already attached"); }else if( rc==SQLITE_OK ){ Pager *pPager; @@ -98925,11 +97762,10 @@ NameContext sName; Vdbe *v; sqlite3* db = pParse->db; int regArgs; - if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || @@ -99479,14 +98315,14 @@ /* ** The TableLock structure is only used by the sqlite3TableLock() and ** codeTableLocks() functions. */ struct TableLock { - int iDb; /* The database containing the table to be locked */ - int iTab; /* The root page of the table to be locked */ - u8 isWriteLock; /* True for write lock. False for a read lock */ - const char *zLockName; /* Name of the table */ + int iDb; /* The database containing the table to be locked */ + int iTab; /* The root page of the table to be locked */ + u8 isWriteLock; /* True for write lock. False for a read lock */ + const char *zName; /* Name of the table */ }; /* ** Record the fact that we want to lock a table at run-time. ** @@ -99508,12 +98344,10 @@ int i; int nBytes; TableLock *p; assert( iDb>=0 ); - if( iDb==1 ) return; - if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return; for(i=0; inTableLock; i++){ p = &pToplevel->aTableLock[i]; if( p->iDb==iDb && p->iTab==iTab ){ p->isWriteLock = (p->isWriteLock || isWriteLock); return; @@ -99526,11 +98360,11 @@ if( pToplevel->aTableLock ){ p = &pToplevel->aTableLock[pToplevel->nTableLock++]; p->iDb = iDb; p->iTab = iTab; p->isWriteLock = isWriteLock; - p->zLockName = zName; + p->zName = zName; }else{ pToplevel->nTableLock = 0; sqlite3OomFault(pToplevel->db); } } @@ -99548,11 +98382,11 @@ for(i=0; inTableLock; i++){ TableLock *p = &pParse->aTableLock[i]; int p1 = p->iDb; sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, - p->zLockName, P4_STATIC); + p->zName, P4_STATIC); } } #else #define codeTableLocks(x) #endif @@ -99757,26 +98591,19 @@ ** exists */ if( db->auth.authLevelnDb; i++){ - int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){ - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); - if( p ) return p; - } - } - /* Not found. If the name we were looking for was temp.sqlite_master - ** then change the name to sqlite_temp_master and try again. */ - if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break; - if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break; - zName = TEMP_MASTER_NAME; - } - return 0; + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){ + assert( sqlite3SchemaMutexHeld(db, j, 0) ); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); + if( p ) break; + } + } + return p; } /* ** Locate the in-memory structure that describes a particular database ** table given the name of that table and (optionally) the name of the @@ -99808,13 +98635,10 @@ if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ /* If zName is the not the name of a table in the schema created using ** CREATE, then check to see if it is the name of an virtual table that ** can be an eponymous virtual table. */ Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); - if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ - pMod = sqlite3PragmaVtabRegister(pParse->db, zName); - } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ return pMod->pEpoTab; } } #endif @@ -100093,11 +98917,11 @@ assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); } SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ /* Do not delete the table until the reference count reaches zero. */ if( !pTable ) return; - if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return; + if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return; deleteTable(db, pTable); } /* @@ -100147,11 +98971,11 @@ ** Open the sqlite_master table stored in database number iDb for ** writing. The table is opened using cursor 0. */ SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ Vdbe *v = sqlite3GetVdbe(p); - sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5); if( p->nTab==0 ){ p->nTab = 1; } } @@ -100165,14 +98989,11 @@ SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){ int i = -1; /* Database number */ if( zName ){ Db *pDb; for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ - if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break; - /* "main" is always an acceptable alias for the primary database - ** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */ - if( i==0 && 0==sqlite3_stricmp("main", zName) ) break; + if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break; } } return i; } @@ -100387,11 +99208,11 @@ goto begin_table_error; } pTable->zName = zName; pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; - pTable->nTabRef = 1; + pTable->nRef = 1; pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, @@ -100564,11 +99385,10 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ Table *p; p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; p->aCol[p->nCol-1].notNull = (u8)onError; - p->tabFlags |= TF_HasNotNull; } /* ** Scan the column type name zType (length nType) and return the ** associated affinity type. @@ -101454,11 +100274,11 @@ */ sqlite3NestedParse(pParse, "UPDATE %Q.%s " "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zDbSName, MASTER_NAME, + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zType, p->zName, p->zName, pParse->regRoot, zStmt, @@ -101791,11 +100611,11 @@ ** is in register NNN. See grammar rules associated with the TK_REGISTER ** token for additional information. */ sqlite3NestedParse(pParse, "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", - pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1); + pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1); #endif sqlite3ReleaseTempReg(pParse, r1); } /* @@ -101934,11 +100754,11 @@ ** created in the temp database that refers to a table in another ** database. */ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", - pDb->zDbSName, MASTER_NAME, pTab->zName); + pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName); if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } /* Remove the table entry from SQLite's internal schema and modify @@ -102281,11 +101101,11 @@ }else{ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); @@ -102826,11 +101646,11 @@ /* Add an entry in sqlite_master for this index */ sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zDbSName, MASTER_NAME, + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName, pTab->zName, iMem, zStmt ); @@ -102904,13 +101724,10 @@ LogEst aVal[] = { 33, 32, 30, 28, 26 }; LogEst *a = pIdx->aiRowLogEst; int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol); int i; - /* Indexes with default row estimates should not have stat1 data */ - assert( !pIdx->hasStat1 ); - /* Set the first entry (number of rows in the index) to the estimated ** number of rows in the table, or half the number of rows in the table ** for a partial index. But do not let the estimate drop below 10. */ a[0] = pIdx->pTable->nRowLogEst; if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) ); @@ -102981,11 +101798,11 @@ v = sqlite3GetVdbe(pParse); if( v ){ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", - db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName ); sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); sqlite3ChangeCookie(pParse, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); @@ -103124,11 +101941,11 @@ assert( iStart<=pSrc->nSrc ); /* Allocate additional space if needed */ if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ SrcList *pNew; - int nAlloc = pSrc->nSrc*2+nExtra; + int nAlloc = pSrc->nSrc+nExtra; int nGot; pNew = sqlite3DbRealloc(db, pSrc, sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) ); if( pNew==0 ){ assert( db->mallocFailed ); @@ -103202,16 +102019,13 @@ assert( db!=0 ); if( pList==0 ){ pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; - pList->nSrc = 1; - memset(&pList->a[0], 0, sizeof(pList->a[0])); - pList->a[0].iCursor = -1; - }else{ - pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); + pList->nSrc = 0; } + pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); if( db->mallocFailed ){ sqlite3SrcListDelete(db, pList); return 0; } pItem = &pList->a[pList->nSrc-1]; @@ -104422,11 +103236,11 @@ assert( pItem && pSrc->nSrc==1 ); pTab = sqlite3LocateTableItem(pParse, 0, pItem); sqlite3DeleteTable(pParse->db, pItem->pTab); pItem->pTab = pTab; if( pTab ){ - pTab->nTabRef++; + pTab->nRef++; } if( sqlite3IndexedByLookup(pParse, pItem) ){ pTab = 0; } return pTab; @@ -104550,11 +103364,11 @@ ** DELETE FROM table_a WHERE rowid IN ( ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 ** ); */ - pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); + pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); if( pSelectRowid == 0 ) goto limit_where_cleanup; pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); if( pEList == 0 ) goto limit_where_cleanup; /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree @@ -104569,12 +103383,12 @@ pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, pOrderBy,0,pLimit,pOffset); if( pSelect == 0 ) return 0; /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ - pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); - pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0; + pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); + pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0; sqlite3PExprAddSelect(pParse, pInClause, pSelect); return pInClause; limit_where_cleanup: sqlite3ExprDelete(pParse->db, pWhere); @@ -104835,11 +103649,11 @@ /* Add the PK key for this row to the temporary table */ iKey = ++pParse->nMem; nKey = 0; /* Zero tells OP_Found to use a composite key */ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, sqlite3IndexAffinityStr(pParse->db, pPk), nPk); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); }else{ /* Add the rowid of the row to be deleted to the RowSet */ nKey = 1; /* OP_Seek always uses a single rowid */ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); } @@ -104881,11 +103695,11 @@ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); VdbeCoverage(v); } }else if( pPk ){ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); + sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey); assert( nKey==0 ); /* OP_Found will use a composite key */ }else{ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); VdbeCoverage(v); assert( nKey==1 ); @@ -104905,12 +103719,16 @@ } }else #endif { int count = (pParse->nested==0); /* True to count changes */ + int iIdxNoSeek = -1; + if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){ + iIdxNoSeek = aiCurOnePass[1]; + } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, - iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]); + iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek); } /* End of the loop over all rowids/primary-keys. */ if( eOnePass!=ONEPASS_OFF ){ sqlite3VdbeResolveLabel(v, addrBypass); @@ -104920,10 +103738,18 @@ sqlite3VdbeJumpHere(v, addrLoop); }else{ sqlite3VdbeGoto(v, addrLoop); sqlite3VdbeJumpHere(v, addrLoop); } + + /* Close the cursors open on the table and its indexes. */ + if( !isView && !IsVirtual(pTab) ){ + if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur); + for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ + sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i); + } + } } /* End non-truncate path */ /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. @@ -104986,21 +103812,19 @@ ** then this function must seek iDataCur to the entry identified by iPk ** and nPk before reading from it. ** ** If eMode is ONEPASS_MULTI, then this call is being made as part ** of a ONEPASS delete that affects multiple rows. In this case, if -** iIdxNoSeek is a valid cursor number (>=0) and is not the same as -** iDataCur, then its position should be preserved following the delete -** operation. Or, if iIdxNoSeek is not a valid cursor number, the -** position of iDataCur should be preserved instead. +** iIdxNoSeek is a valid cursor number (>=0), then its position should +** be preserved following the delete operation. Or, if iIdxNoSeek is not +** a valid cursor number, the position of iDataCur should be preserved +** instead. ** ** iIdxNoSeek: -** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur, -** then it identifies an index cursor (from within array of cursors -** starting at iIdxCur) that already points to the index entry to be deleted. -** Except, this optimization is disabled if there are BEFORE triggers since -** the trigger body might have moved the cursor. +** If iIdxNoSeek is a valid cursor number (>=0), then it identifies an +** index cursor (from within array of cursors starting at iIdxCur) that +** already points to the index entry to be deleted. */ SQLITE_PRIVATE void sqlite3GenerateRowDelete( Parse *pParse, /* Parsing context */ Table *pTab, /* Table containing the row to be deleted */ Trigger *pTrigger, /* List of triggers to (potentially) fire */ @@ -105067,22 +103891,17 @@ TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel ); /* If any BEFORE triggers were coded, then seek the cursor to the ** row to be deleted again. It may be that the BEFORE triggers moved - ** the cursor or already deleted the row that the cursor was + ** the cursor or of already deleted the row that the cursor was ** pointing to. - ** - ** Also disable the iIdxNoSeek optimization since the BEFORE trigger - ** may have moved that cursor. */ if( addrStart=0 ); - iIdxNoSeek = -1; } /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ @@ -105101,17 +103920,15 @@ */ if( pTab->pSelect==0 ){ u8 p5 = 0; sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); - if( pParse->nested==0 ){ - sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); - } + sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); if( eMode!=ONEPASS_OFF ){ sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); } - if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){ + if( iIdxNoSeek>=0 ){ sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); } if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; sqlite3VdbeChangeP5(v, p5); } @@ -105261,14 +104078,10 @@ ** opcode if it is present */ sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); } if( regOut ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); - if( pIdx->pTable->pSelect ){ - const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx); - sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); - } } sqlite3ReleaseTempRange(pParse, regBase, nCol); return regBase; } @@ -105486,30 +104299,27 @@ typeHaystack = sqlite3_value_type(argv[0]); typeNeedle = sqlite3_value_type(argv[1]); if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; nHaystack = sqlite3_value_bytes(argv[0]); nNeedle = sqlite3_value_bytes(argv[1]); - if( nNeedle>0 ){ - if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ - zHaystack = sqlite3_value_blob(argv[0]); - zNeedle = sqlite3_value_blob(argv[1]); - isText = 0; - }else{ - zHaystack = sqlite3_value_text(argv[0]); - zNeedle = sqlite3_value_text(argv[1]); - isText = 1; - } - if( zNeedle==0 || (nHaystack && zHaystack==0) ) return; - while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ - N++; - do{ - nHaystack--; - zHaystack++; - }while( isText && (zHaystack[0]&0xc0)==0x80 ); - } - if( nNeedle>nHaystack ) N = 0; - } + if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ + zHaystack = sqlite3_value_blob(argv[0]); + zNeedle = sqlite3_value_blob(argv[1]); + isText = 0; + }else{ + zHaystack = sqlite3_value_text(argv[0]); + zNeedle = sqlite3_value_text(argv[1]); + isText = 1; + } + while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ + N++; + do{ + nHaystack--; + zHaystack++; + }while( isText && (zHaystack[0]&0xc0)==0x80 ); + } + if( nNeedle>nHaystack ) N = 0; sqlite3_result_int(context, N); } /* ** Implementation of the printf() function. @@ -105885,23 +104695,13 @@ /* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator ** is case sensitive causing 'a' LIKE 'A' to be false */ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; /* -** Possible error returns from patternMatch() -*/ -#define SQLITE_MATCH 0 -#define SQLITE_NOMATCH 1 -#define SQLITE_NOWILDCARDMATCH 2 - -/* -** Compare two UTF-8 strings for equality where the first string is -** a GLOB or LIKE expression. Return values: -** -** SQLITE_MATCH: Match -** SQLITE_NOMATCH: No match -** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards. +** Compare two UTF-8 strings for equality where the first string can +** potentially be a "glob" or "like" expression. Return true (1) if they +** are the same and false (0) if they are different. ** ** Globbing rules: ** ** '*' Matches any sequence of zero or more characters. ** @@ -105948,76 +104748,71 @@ /* Skip over multiple "*" characters in the pattern. If there ** are also "?" characters, skip those as well, but consume a ** single character of the input string for each "?" skipped */ while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ - return SQLITE_NOWILDCARDMATCH; + return 0; } } if( c==0 ){ - return SQLITE_MATCH; /* "*" at the end of the pattern matches */ + return 1; /* "*" at the end of the pattern matches */ }else if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return SQLITE_NOWILDCARDMATCH; + if( c==0 ) return 0; }else{ /* "[...]" immediately follows the "*". We have to do a slow ** recursive search in this case, but it is an unusual case. */ assert( matchOther<0x80 ); /* '[' is a single-byte character */ - while( *zString ){ - int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther); - if( bMatch!=SQLITE_NOMATCH ) return bMatch; + while( *zString + && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){ SQLITE_SKIP_UTF8(zString); } - return SQLITE_NOWILDCARDMATCH; + return *zString!=0; } } /* At this point variable c contains the first character of the ** pattern string past the "*". Search in the input string for the - ** first matching character and recursively continue the match from + ** first matching character and recursively contine the match from ** that point. ** ** For a case-insensitive search, set variable cx to be the same as ** c but in the other case and search the input string for either ** c or cx. */ if( c<=0x80 ){ u32 cx; - int bMatch; if( noCase ){ cx = sqlite3Toupper(c); c = sqlite3Tolower(c); }else{ cx = c; } while( (c2 = *(zString++))!=0 ){ if( c2!=c && c2!=cx ) continue; - bMatch = patternCompare(zPattern,zString,pInfo,matchOther); - if( bMatch!=SQLITE_NOMATCH ) return bMatch; + if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1; } }else{ - int bMatch; while( (c2 = Utf8Read(zString))!=0 ){ if( c2!=c ) continue; - bMatch = patternCompare(zPattern,zString,pInfo,matchOther); - if( bMatch!=SQLITE_NOMATCH ) return bMatch; + if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1; } } - return SQLITE_NOWILDCARDMATCH; + return 0; } if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); - if( c==0 ) return SQLITE_NOMATCH; + if( c==0 ) return 0; zEscaped = zPattern; }else{ u32 prior_c = 0; int seen = 0; int invert = 0; c = sqlite3Utf8Read(&zString); - if( c==0 ) return SQLITE_NOMATCH; + if( c==0 ) return 0; c2 = sqlite3Utf8Read(&zPattern); if( c2=='^' ){ invert = 1; c2 = sqlite3Utf8Read(&zPattern); } @@ -106037,11 +104832,11 @@ prior_c = c2; } c2 = sqlite3Utf8Read(&zPattern); } if( c2==0 || (seen ^ invert)==0 ){ - return SQLITE_NOMATCH; + return 0; } continue; } } c2 = Utf8Read(zString); @@ -106048,29 +104843,27 @@ if( c==c2 ) continue; if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) && c<0x80 && c2<0x80 ){ continue; } if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue; - return SQLITE_NOMATCH; + return 0; } - return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH; + return *zString==0; } /* -** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and -** non-zero if there is no match. +** The sqlite3_strglob() interface. */ SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){ - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '['); + return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0; } /* -** The sqlite3_strlike() interface. Return 0 on a match and non-zero for -** a miss - like strcmp(). +** The sqlite3_strlike() interface. */ SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc); + return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0; } /* ** Count the number of times that the LIKE operator (or GLOB which is ** just a variation of LIKE) gets called. This is used for testing @@ -106147,11 +104940,11 @@ } if( zA && zB ){ #ifdef SQLITE_TEST sqlite3_like_count++; #endif - sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH); + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); } } /* ** Implementation of the NULLIF(x,y) function. The result is the first @@ -106918,11 +105711,11 @@ nSep = sqlite3_value_bytes(argv[1]); }else{ zSep = ","; nSep = 1; } - if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); + if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep); } zVal = (char*)sqlite3_value_text(argv[0]); nVal = sqlite3_value_bytes(argv[0]); if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal); } @@ -107059,13 +105852,10 @@ DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), -#ifdef SQLITE_DEBUG - FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), -#endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), FUNCTION(rtrim, 2, 2, 0, trimFunc ), FUNCTION(trim, 1, 3, 0, trimFunc ), @@ -107384,11 +106174,11 @@ if( !aiCol ) return 1; *paiCol = aiCol; } for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){ + if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){ /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number ** of columns. If each indexed column corresponds to a foreign key ** column of pFKey, then this index is a winner. */ if( zKey==0 ){ @@ -107743,11 +106533,11 @@ pLeft = exprTableRegister(pParse, pTab, regData, iCol); iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iCol>=0 ); zCol = pFKey->pFrom->aCol[iCol].zName; pRight = sqlite3Expr(db, TK_ID, zCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); + pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); } /* If the child table is the same as the parent table, then add terms ** to the WHERE clause that prevent this entry from being scanned. @@ -107765,24 +106555,24 @@ Expr *pLeft; /* Value from parent table row */ Expr *pRight; /* Column ref to child table */ if( HasRowid(pTab) ){ pLeft = exprTableRegister(pParse, pTab, regData, -1); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1); - pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight); + pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0); }else{ Expr *pEq, *pAll = 0; Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pIdx!=0 ); for(i=0; inKeyCol; i++){ i16 iCol = pIdx->aiColumn[i]; assert( iCol>=0 ); pLeft = exprTableRegister(pParse, pTab, regData, iCol); pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol); - pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); + pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0); pAll = sqlite3ExprAnd(db, pAll, pEq); } - pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0); + pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0); } pWhere = sqlite3ExprAnd(db, pWhere, pNe); } /* Resolve the references in the WHERE clause. */ @@ -108166,11 +106956,11 @@ pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ struct SrcList_item *pItem = pSrc->a; pItem->pTab = pFKey->pFrom; pItem->zName = pFKey->pFrom->zName; - pItem->pTab->nTabRef++; + pItem->pTab->nRef++; pItem->iCursor = pParse->nTab++; if( regNew!=0 ){ fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); } @@ -108364,13 +107154,14 @@ ** that the affinity and collation sequence associated with the ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) + , 0), sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) - ); + , 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); /* For ON UPDATE, construct the next term of the WHEN clause. ** The final WHEN clause will be like this: ** @@ -108378,24 +107169,27 @@ */ if( pChanges ){ pEq = sqlite3PExpr(pParse, TK_IS, sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tOld, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), + 0), sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)) - ); + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), + 0), + 0); pWhen = sqlite3ExprAnd(db, pWhen, pEq); } if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){ Expr *pNew; if( action==OE_Cascade ){ pNew = sqlite3PExpr(pParse, TK_DOT, sqlite3ExprAlloc(db, TK_ID, &tNew, 0), - sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)); + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) + , 0); }else if( action==OE_SetDflt ){ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; if( pDflt ){ pNew = sqlite3ExprDup(db, pDflt, 0); }else{ @@ -108447,11 +107241,11 @@ pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); if( pWhen ){ - pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0); + pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0); pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); } } /* Re-enable the lookaside buffer, if it was disabled earlier. */ @@ -109051,11 +107845,11 @@ int onError /* How to handle constraint errors */ ){ sqlite3 *db; /* The main database structure */ Table *pTab; /* The table to insert into. aka TABLE */ char *zTab; /* Name of the table into which we are inserting */ - int i, j; /* Loop counters */ + int i, j, idx; /* Loop counters */ Vdbe *v; /* Generate code into this virtual machine */ Index *pIdx; /* For looping over indices of the table */ int nColumn; /* Number of columns in the data */ int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ int iDataCur = 0; /* VDBE cursor that is the main data repository */ @@ -109358,14 +108152,12 @@ &iDataCur, &iIdxCur); aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } - for(i=0, pIdx=pTab->pIndex; ipNext, i++){ - assert( pIdx ); + for(i=0; inMem; - pParse->nMem += pIdx->nColumn; } } /* This is the top of the main insertion loop */ if( useTempTable ){ @@ -109563,30 +108355,16 @@ sqlite3MayAbort(pParse); }else #endif { int isReplace; /* Set to true if constraints may cause a replace */ - int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0 ); sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0); - - /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE - ** constraints or (b) there are no triggers and this table is not a - ** parent table in a foreign key constraint. It is safe to set the - ** flag in the second case as if any REPLACE constraint is hit, an - ** OP_Delete or OP_IdxDelete instruction will be executed on each - ** cursor that is disturbed. And these instructions both clear the - ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT - ** functionality. */ - bUseSeek = (isReplace==0 || (pTrigger==0 && - ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0) - )); sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, - regIns, aRegIdx, 0, appendFlag, bUseSeek - ); + regIns, aRegIdx, 0, appendFlag, isReplace==0); } } /* Update the count of rows that are inserted */ @@ -109610,10 +108388,18 @@ sqlite3VdbeAddOp1(v, OP_Close, srcTab); }else if( pSelect ){ sqlite3VdbeGoto(v, addrCont); sqlite3VdbeJumpHere(v, addrInsTop); } + + if( !IsVirtual(pTab) && !isView ){ + /* Close all tables opened */ + if( iDataCurpIndex; pIdx; pIdx=pIdx->pNext, idx++){ + sqlite3VdbeAddOp1(v, OP_Close, idx+iIdxCur); + } + } insert_end: /* Update the sqlite_sequence table by storing the content of the ** maximum rowid counter values recorded while inserting into ** autoincrement tables. @@ -109817,10 +108603,11 @@ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */ int ipkTop = 0; /* Top of the rowid change constraint check */ int ipkBottom = 0; /* Bottom of the rowid change constraint check */ u8 isUpdate; /* True if this is an UPDATE operation */ u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */ + int regRowid = -1; /* Register holding ROWID value */ isUpdate = regOldData!=0; db = pParse->db; v = sqlite3GetVdbe(pParse); assert( v!=0 ); @@ -109871,13 +108658,12 @@ /* Fall through */ case OE_Rollback: case OE_Fail: { char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, pTab->aCol[i].zName); - sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, - regNewData+1+i); - sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); + sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, + regNewData+1+i, zMsg, P4_DYNAMIC); sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); VdbeCoverage(v); break; } case OE_Ignore: { @@ -109937,11 +108723,11 @@ }else if( onError==OE_Default ){ onError = OE_Abort; } if( isUpdate ){ - /* pkChng!=0 does not mean that the rowid has changed, only that + /* pkChng!=0 does not mean that the rowid has change, only that ** it might have changed. Skip the conflict logic below if the rowid ** is unchanged. */ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData); sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); VdbeCoverage(v); @@ -110015,11 +108801,11 @@ /* This OP_Delete opcode fires the pre-update-hook only. It does ** not modify the b-tree. It is more efficient to let the coming ** OP_Insert replace the existing entry than it is to delete the ** existing entry and then insert a new one. */ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP); - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ if( pTab->pIndex ){ sqlite3MultiWrite(pParse); sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,-1); @@ -110072,11 +108858,11 @@ } /* Create a record for this index entry as it should appear after ** the insert or update. Store that record in the aRegIdx[ix] register */ - regIdx = aRegIdx[ix]+1; + regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn); for(i=0; inColumn; i++){ int iField = pIdx->aiColumn[i]; int x; if( iField==XN_EXPR ){ pParse->ckBase = regNewData+1; @@ -110083,23 +108869,23 @@ sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i); pParse->ckBase = 0; VdbeComment((v, "%s column %d", pIdx->zName, i)); }else{ if( iField==XN_ROWID || iField==pTab->iPKey ){ + if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */ x = regNewData; + regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i; }else{ x = iField + regNewData + 1; } sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i); VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName)); } } sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); -#ifdef SQLITE_ENABLE_NULL_TRIM - if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable); -#endif + sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn); /* In an UPDATE operation, if this index is the PRIMARY KEY index ** of a WITHOUT ROWID table and there has been no change the ** primary key, then no collision is possible. The collision detection ** logic below can all be skipped. */ @@ -110109,38 +108895,20 @@ } /* Find out what action to take in case there is a uniqueness conflict */ onError = pIdx->onError; if( onError==OE_None ){ + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; /* pIdx is not a UNIQUE index */ } if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = OE_Abort; } - - /* Collision detection may be omitted if all of the following are true: - ** (1) The conflict resolution algorithm is REPLACE - ** (2) The table is a WITHOUT ROWID table - ** (3) There are no secondary indexes on the table - ** (4) No delete triggers need to be fired if there is a conflict - ** (5) No FK constraint counters need to be updated if a conflict occurs. - */ - if( (ix==0 && pIdx->pNext==0) /* Condition 3 */ - && pPk==pIdx /* Condition 2 */ - && onError==OE_Replace /* Condition 1 */ - && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */ - 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0)) - && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */ - (0==pTab->pFKey && 0==sqlite3FkReferences(pTab))) - ){ - sqlite3VdbeResolveLabel(v, addrUniqueOk); - continue; - } - + /* Check to see if the new index entry will be unique */ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); VdbeCoverage(v); /* Generate code to handle collisions */ @@ -110220,16 +108988,17 @@ if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, regR, nPkField, 0, OE_Replace, - (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur); + (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1); seenReplace = 1; break; } } sqlite3VdbeResolveLabel(v, addrUniqueOk); + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } if( ipkTop ){ sqlite3VdbeGoto(v, ipkTop+1); sqlite3VdbeJumpHere(v, ipkBottom); @@ -110237,32 +109006,10 @@ *pbMayReplace = seenReplace; VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace)); } -#ifdef SQLITE_ENABLE_NULL_TRIM -/* -** Change the P5 operand on the last opcode (which should be an OP_MakeRecord) -** to be the number of columns in table pTab that must not be NULL-trimmed. -** -** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero. -*/ -SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){ - u16 i; - - /* Records with omitted columns are only allowed for schema format - ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */ - if( pTab->pSchema->file_format<2 ) return; - - for(i=pTab->nCol-1; i>0; i--){ - if( pTab->aCol[i].pDflt!=0 ) break; - if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break; - } - sqlite3VdbeChangeP5(v, i+1); -} -#endif - /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqlite3GenerateConstraintChecks. ** A consecutive range of registers starting at regNewData contains the ** rowid and the content to be inserted. @@ -110275,11 +109022,11 @@ Table *pTab, /* the table into which we are inserting */ int iDataCur, /* Cursor of the canonical data source */ int iIdxCur, /* First index cursor */ int regNewData, /* Range of content */ int *aRegIdx, /* Register used by each index. 0 for unused indices */ - int update_flags, /* True for UPDATE, False for INSERT */ + int isUpdate, /* True for UPDATE, False for INSERT */ int appendBias, /* True if this is likely to be an append */ int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ ){ Vdbe *v; /* Prepared statements under construction */ Index *pIdx; /* An index being inserted or updated */ @@ -110287,15 +109034,10 @@ int regData; /* Content registers (after the rowid) */ int regRec; /* Register holding assembled record for the table */ int i; /* Loop counter */ u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */ - assert( update_flags==0 - || update_flags==OPFLAG_ISUPDATE - || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION) - ); - v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( aRegIdx[i]==0 ) continue; @@ -110302,53 +109044,40 @@ bAffinityDone = 1; if( pIdx->pPartIdxWhere ){ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2); VdbeCoverage(v); } - pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]); + pik_flags = 0; + if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT; if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ assert( pParse->nested==0 ); pik_flags |= OPFLAG_NCHANGE; - pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); -#ifdef SQLITE_ENABLE_PREUPDATE_HOOK - if( update_flags==0 ){ - sqlite3VdbeAddOp4(v, OP_InsertInt, - iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE - ); - sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP); - } -#endif - } - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i], - aRegIdx[i]+1, - pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn); + } sqlite3VdbeChangeP5(v, pik_flags); } if( !HasRowid(pTab) ) return; regData = regNewData + 1; regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); - sqlite3SetMakeRecordP5(v, pTab); - if( !bAffinityDone ){ - sqlite3TableAffinity(v, pTab, 0); - sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); - } + if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0); + sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE; - pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID); + pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } if( appendBias ){ pik_flags |= OPFLAG_APPEND; } if( useSeekResult ){ pik_flags |= OPFLAG_USESEEKRESULT; } sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData); if( !pParse->nested ){ - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE); } sqlite3VdbeChangeP5(v, pik_flags); } /* @@ -110545,11 +109274,11 @@ } if( sqlite3TriggerList(pParse, pDest) ){ return 0; /* tab1 must not have triggers */ } #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pDest) ){ + if( pDest->tabFlags & TF_Virtual ){ return 0; /* tab1 must not be a virtual table */ } #endif if( onError==OE_Default ){ if( pDest->iPKey>=0 ) onError = pDest->keyConf; @@ -110607,11 +109336,11 @@ } if( HasRowid(pDest)!=HasRowid(pSrc) ){ return 0; /* source and destination must both be WITHOUT ROWID or not */ } #ifndef SQLITE_OMIT_VIRTUALTABLE - if( IsVirtual(pSrc) ){ + if( pSrc->tabFlags & TF_Virtual ){ return 0; /* tab2 must not be a virtual table */ } #endif if( pSrc->pSelect ){ return 0; /* tab2 may not be a view */ @@ -110727,11 +109456,10 @@ addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); VdbeCoverage(v); emptyDestTest = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); } if( HasRowid(pSrc) ){ - u8 insFlags; sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); @@ -110743,21 +109471,14 @@ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); assert( (pDest->tabFlags & TF_Autoincrement)==0 ); } - sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); - if( db->flags & SQLITE_Vacuum ){ - sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); - insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID| - OPFLAG_APPEND|OPFLAG_USESEEKRESULT; - }else{ - insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND; - } + sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid, (char*)pDest, P4_TABLE); - sqlite3VdbeChangeP5(v, insFlags); + sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); }else{ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName); @@ -110775,11 +109496,11 @@ sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest); sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx); sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR); VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1); + sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); if( db->flags & SQLITE_Vacuum ){ /* This INSERT command is part of a VACUUM operation, which guarantees ** that the destination table is empty. If all indexed columns use ** collation sequence BINARY, then it can also be assumed that the ** index will be populated by inserting keys in strictly sorted @@ -110793,10 +109514,12 @@ ** might change the definition of a collation sequence and then run ** a VACUUM command. In that case keys may not be written in strictly ** sorted order. */ for(i=0; inColumn; i++){ const char *zColl = pSrcIdx->azColl[i]; + assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0 + || sqlite3StrBINARY==zColl ); if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break; } if( i==pSrcIdx->nColumn ){ idxInsFlags = OPFLAG_USESEEKRESULT; sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); @@ -110803,12 +109526,12 @@ } } if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ idxInsFlags |= OPFLAG_NCHANGE; } - sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); - sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); + sqlite3VdbeChangeP5(v, idxInsFlags); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); } @@ -110902,11 +109625,11 @@ /* Invoke the callback function if required */ if( xCallback && (SQLITE_ROW==rc || (SQLITE_DONE==rc && !callbackIsInit && db->flags&SQLITE_NullCallback)) ){ if( !callbackIsInit ){ - azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*)); + azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); if( azCols==0 ){ goto exec_out; } for(i=0; isystem_errno /* Version 3.14.0 and later */ #define sqlite3_trace_v2 sqlite3_api->trace_v2 #define sqlite3_expanded_sql sqlite3_api->expanded_sql -/* Version 3.18.0 and later */ -#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ @@ -111563,10 +110281,11 @@ #endif /* SQLITE3EXT_H */ /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ /* #include "sqliteInt.h" */ +/* #include */ #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Some API routines are omitted when various features are ** excluded from a build of SQLite. Substitute a NULL pointer @@ -111966,13 +110685,11 @@ sqlite3_db_cacheflush, /* Version 3.12.0 and later */ sqlite3_system_errno, /* Version 3.14.0 and later */ sqlite3_trace_v2, - sqlite3_expanded_sql, - /* Version 3.18.0 and later */ - sqlite3_set_last_insert_rowid + sqlite3_expanded_sql }; /* ** Attempt to load an SQLite extension library contained in the file ** zFile. The entry point is zProc. zProc may be 0 in which case a @@ -112373,12 +111090,10 @@ /* DO NOT EDIT! ** This file is automatically generated by the script at ** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit ** that script and rerun it. */ - -/* The various pragma types */ #define PragTyp_HEADER_VALUE 0 #define PragTyp_AUTO_VACUUM 1 #define PragTyp_FLAG 2 #define PragTyp_BUSY_TIMEOUT 3 #define PragTyp_CACHE_SIZE 4 @@ -112400,15 +111115,15 @@ #define PragTyp_JOURNAL_SIZE_LIMIT 20 #define PragTyp_LOCK_PROXY_FILE 21 #define PragTyp_LOCKING_MODE 22 #define PragTyp_PAGE_COUNT 23 #define PragTyp_MMAP_SIZE 24 -#define PragTyp_OPTIMIZE 25 -#define PragTyp_PAGE_SIZE 26 -#define PragTyp_SECURE_DELETE 27 -#define PragTyp_SHRINK_MEMORY 28 -#define PragTyp_SOFT_HEAP_LIMIT 29 +#define PragTyp_PAGE_SIZE 25 +#define PragTyp_SECURE_DELETE 26 +#define PragTyp_SHRINK_MEMORY 27 +#define PragTyp_SOFT_HEAP_LIMIT 28 +#define PragTyp_STATS 29 #define PragTyp_SYNCHRONOUS 30 #define PragTyp_TABLE_INFO 31 #define PragTyp_TEMP_STORE 32 #define PragTyp_TEMP_STORE_DIRECTORY 33 #define PragTyp_THREADS 34 @@ -112418,576 +111133,426 @@ #define PragTyp_HEXKEY 38 #define PragTyp_KEY 39 #define PragTyp_REKEY 40 #define PragTyp_LOCK_STATUS 41 #define PragTyp_PARSER_TRACE 42 -#define PragTyp_STATS 43 - -/* Property flags associated with various pragma. */ -#define PragFlg_NeedSchema 0x01 /* Force schema load before running */ -#define PragFlg_NoColumns 0x02 /* OP_ResultRow called with zero columns */ -#define PragFlg_NoColumns1 0x04 /* zero columns if RHS argument is present */ -#define PragFlg_ReadOnly 0x08 /* Read-only HEADER_VALUE */ -#define PragFlg_Result0 0x10 /* Acts as query when no argument */ -#define PragFlg_Result1 0x20 /* Acts as query when has one argument */ -#define PragFlg_SchemaOpt 0x40 /* Schema restricts name search if present */ -#define PragFlg_SchemaReq 0x80 /* Schema required - "main" is default */ - -/* Names of columns for pragmas that return multi-column result -** or that return single-column results where the name of the -** result column is different from the name of the pragma -*/ -static const char *const pragCName[] = { - /* 0 */ "cache_size", /* Used by: default_cache_size */ - /* 1 */ "cid", /* Used by: table_info */ - /* 2 */ "name", - /* 3 */ "type", - /* 4 */ "notnull", - /* 5 */ "dflt_value", - /* 6 */ "pk", - /* 7 */ "tbl", /* Used by: stats */ - /* 8 */ "idx", - /* 9 */ "wdth", - /* 10 */ "hght", - /* 11 */ "flgs", - /* 12 */ "seqno", /* Used by: index_info */ - /* 13 */ "cid", - /* 14 */ "name", - /* 15 */ "seqno", /* Used by: index_xinfo */ - /* 16 */ "cid", - /* 17 */ "name", - /* 18 */ "desc", - /* 19 */ "coll", - /* 20 */ "key", - /* 21 */ "seq", /* Used by: index_list */ - /* 22 */ "name", - /* 23 */ "unique", - /* 24 */ "origin", - /* 25 */ "partial", - /* 26 */ "seq", /* Used by: database_list */ - /* 27 */ "name", - /* 28 */ "file", - /* 29 */ "seq", /* Used by: collation_list */ - /* 30 */ "name", - /* 31 */ "id", /* Used by: foreign_key_list */ - /* 32 */ "seq", - /* 33 */ "table", - /* 34 */ "from", - /* 35 */ "to", - /* 36 */ "on_update", - /* 37 */ "on_delete", - /* 38 */ "match", - /* 39 */ "table", /* Used by: foreign_key_check */ - /* 40 */ "rowid", - /* 41 */ "parent", - /* 42 */ "fkid", - /* 43 */ "busy", /* Used by: wal_checkpoint */ - /* 44 */ "log", - /* 45 */ "checkpointed", - /* 46 */ "timeout", /* Used by: busy_timeout */ - /* 47 */ "database", /* Used by: lock_status */ - /* 48 */ "status", -}; - -/* Definitions of all built-in pragmas */ -typedef struct PragmaName { - const char *const zName; /* Name of pragma */ - u8 ePragTyp; /* PragTyp_XXX value */ - u8 mPragFlg; /* Zero or more PragFlg_XXX values */ - u8 iPragCName; /* Start of column names in pragCName[] */ - u8 nPragCName; /* Num of col names. 0 means use pragma name */ - u32 iArg; /* Extra argument */ -} PragmaName; -static const PragmaName aPragmaName[] = { -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) - {/* zName: */ "activate_extensions", - /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "application_id", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_APPLICATION_ID }, -#endif -#if !defined(SQLITE_OMIT_AUTOVACUUM) - {/* zName: */ "auto_vacuum", - /* ePragTyp: */ PragTyp_AUTO_VACUUM, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) - {/* zName: */ "automatic_index", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_AutoIndex }, -#endif -#endif - {/* zName: */ "busy_timeout", - /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 46, 1, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "cache_size", - /* ePragTyp: */ PragTyp_CACHE_SIZE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_CACHE_SPILL, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif - {/* zName: */ "case_sensitive_like", - /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, - /* ePragFlg: */ PragFlg_NoColumns, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "cell_size_check", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_CellSizeCk }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "checkpoint_fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_CkptFullFSync }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "collation_list", - /* ePragTyp: */ PragTyp_COLLATION_LIST, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 29, 2, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) - {/* zName: */ "compile_options", - /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "count_changes", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_CountRows }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN - {/* zName: */ "data_store_directory", - /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, - /* ePragFlg: */ PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "data_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_DATA_VERSION }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "database_list", - /* ePragTyp: */ PragTyp_DATABASE_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, - /* ColNames: */ 26, 3, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) - {/* zName: */ "default_cache_size", - /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 1, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - {/* zName: */ "defer_foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_DeferFKs }, -#endif -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "empty_result_callbacks", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_NullCallback }, -#endif -#if !defined(SQLITE_OMIT_UTF16) - {/* zName: */ "encoding", - /* ePragTyp: */ PragTyp_ENCODING, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - {/* zName: */ "foreign_key_check", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 39, 4, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FOREIGN_KEY) - {/* zName: */ "foreign_key_list", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 31, 8, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - {/* zName: */ "foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ForeignKeys }, -#endif -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "freelist_count", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_ReadOnly|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_FREE_PAGE_COUNT }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "full_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_FullColNames }, - {/* zName: */ "fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_FullFSync }, -#endif -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "hexkey", - /* ePragTyp: */ PragTyp_HEXKEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "hexrekey", - /* ePragTyp: */ PragTyp_HEXKEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_CHECK) - {/* zName: */ "ignore_check_constraints", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_IgnoreChecks }, -#endif -#endif -#if !defined(SQLITE_OMIT_AUTOVACUUM) - {/* zName: */ "incremental_vacuum", - /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_NoColumns, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "index_info", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 12, 3, - /* iArg: */ 0 }, - {/* zName: */ "index_list", - /* ePragTyp: */ PragTyp_INDEX_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 21, 5, - /* iArg: */ 0 }, - {/* zName: */ "index_xinfo", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 15, 6, - /* iArg: */ 1 }, -#endif -#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - {/* zName: */ "integrity_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "journal_mode", - /* ePragTyp: */ PragTyp_JOURNAL_MODE, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "journal_size_limit", - /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "key", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "legacy_file_format", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_LegacyFileFmt }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE - {/* zName: */ "lock_proxy_file", - /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, - /* ePragFlg: */ PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - {/* zName: */ "lock_status", - /* ePragTyp: */ PragTyp_LOCK_STATUS, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 47, 2, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "locking_mode", - /* ePragTyp: */ PragTyp_LOCKING_MODE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "max_page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "mmap_size", - /* ePragTyp: */ PragTyp_MMAP_SIZE, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif - {/* zName: */ "optimize", - /* ePragTyp: */ PragTyp_OPTIMIZE, - /* ePragFlg: */ PragFlg_Result1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "page_size", - /* ePragTyp: */ PragTyp_PAGE_SIZE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE) - {/* zName: */ "parser_trace", - /* ePragTyp: */ PragTyp_PARSER_TRACE, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "query_only", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_QueryOnly }, -#endif -#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - {/* zName: */ "quick_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "read_uncommitted", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ReadUncommitted }, - {/* zName: */ "recursive_triggers", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_RecTriggers }, -#endif -#if defined(SQLITE_HAS_CODEC) - {/* zName: */ "rekey", - /* ePragTyp: */ PragTyp_REKEY, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "reverse_unordered_selects", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ReverseOrder }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "schema_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_SCHEMA_VERSION }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "secure_delete", - /* ePragTyp: */ PragTyp_SECURE_DELETE, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "short_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_ShortColNames }, -#endif - {/* zName: */ "shrink_memory", - /* ePragTyp: */ PragTyp_SHRINK_MEMORY, - /* ePragFlg: */ PragFlg_NoColumns, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "soft_heap_limit", - /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - {/* zName: */ "sql_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_SqlTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) && defined(SQLITE_DEBUG) - {/* zName: */ "stats", - /* ePragTyp: */ PragTyp_STATS, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 7, 5, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "synchronous", - /* ePragTyp: */ PragTyp_SYNCHRONOUS, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - {/* zName: */ "table_info", - /* ePragTyp: */ PragTyp_TABLE_INFO, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 1, 6, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - {/* zName: */ "temp_store", - /* ePragTyp: */ PragTyp_TEMP_STORE, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "temp_store_directory", - /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, - /* ePragFlg: */ PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#endif - {/* zName: */ "threads", - /* ePragTyp: */ PragTyp_THREADS, - /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - {/* zName: */ "user_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlg: */ PragFlg_NoColumns1|PragFlg_Result0, - /* ColNames: */ 0, 0, - /* iArg: */ BTREE_USER_VERSION }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - {/* zName: */ "vdbe_addoptrace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeAddopTrace }, - {/* zName: */ "vdbe_debug", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, - {/* zName: */ "vdbe_eqp", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeEQP }, - {/* zName: */ "vdbe_listing", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeListing }, - {/* zName: */ "vdbe_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_VdbeTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_WAL) - {/* zName: */ "wal_autocheckpoint", - /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, - /* ePragFlg: */ 0, - /* ColNames: */ 0, 0, - /* iArg: */ 0 }, - {/* zName: */ "wal_checkpoint", - /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, - /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 43, 3, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - {/* zName: */ "writable_schema", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, - /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, -#endif -}; -/* Number of pragmas: 60 on by default, 74 total. */ +#define PragFlag_NeedSchema 0x01 +#define PragFlag_ReadOnly 0x02 +static const struct sPragmaNames { + const char *const zName; /* Name of pragma */ + u8 ePragTyp; /* PragTyp_XXX value */ + u8 mPragFlag; /* Zero or more PragFlag_XXX values */ + u32 iArg; /* Extra argument */ +} aPragmaNames[] = { +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) + { /* zName: */ "activate_extensions", + /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "application_id", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ 0, + /* iArg: */ BTREE_APPLICATION_ID }, +#endif +#if !defined(SQLITE_OMIT_AUTOVACUUM) + { /* zName: */ "auto_vacuum", + /* ePragTyp: */ PragTyp_AUTO_VACUUM, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) + { /* zName: */ "automatic_index", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_AutoIndex }, +#endif +#endif + { /* zName: */ "busy_timeout", + /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "cache_size", + /* ePragTyp: */ PragTyp_CACHE_SIZE, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "cache_spill", + /* ePragTyp: */ PragTyp_CACHE_SPILL, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif + { /* zName: */ "case_sensitive_like", + /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "cell_size_check", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_CellSizeCk }, +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "checkpoint_fullfsync", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_CkptFullFSync }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "collation_list", + /* ePragTyp: */ PragTyp_COLLATION_LIST, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) + { /* zName: */ "compile_options", + /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "count_changes", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_CountRows }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN + { /* zName: */ "data_store_directory", + /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "data_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ PragFlag_ReadOnly, + /* iArg: */ BTREE_DATA_VERSION }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "database_list", + /* ePragTyp: */ PragTyp_DATABASE_LIST, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) + { /* zName: */ "default_cache_size", + /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + { /* zName: */ "defer_foreign_keys", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_DeferFKs }, +#endif +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "empty_result_callbacks", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_NullCallback }, +#endif +#if !defined(SQLITE_OMIT_UTF16) + { /* zName: */ "encoding", + /* ePragTyp: */ PragTyp_ENCODING, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + { /* zName: */ "foreign_key_check", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FOREIGN_KEY) + { /* zName: */ "foreign_key_list", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + { /* zName: */ "foreign_keys", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ForeignKeys }, +#endif +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "freelist_count", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ PragFlag_ReadOnly, + /* iArg: */ BTREE_FREE_PAGE_COUNT }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "full_column_names", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_FullColNames }, + { /* zName: */ "fullfsync", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_FullFSync }, +#endif +#if defined(SQLITE_HAS_CODEC) + { /* zName: */ "hexkey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "hexrekey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_CHECK) + { /* zName: */ "ignore_check_constraints", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_IgnoreChecks }, +#endif +#endif +#if !defined(SQLITE_OMIT_AUTOVACUUM) + { /* zName: */ "incremental_vacuum", + /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "index_info", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "index_list", + /* ePragTyp: */ PragTyp_INDEX_LIST, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "index_xinfo", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 1 }, +#endif +#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) + { /* zName: */ "integrity_check", + /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "journal_mode", + /* ePragTyp: */ PragTyp_JOURNAL_MODE, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "journal_size_limit", + /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if defined(SQLITE_HAS_CODEC) + { /* zName: */ "key", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "legacy_file_format", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_LegacyFileFmt }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE + { /* zName: */ "lock_proxy_file", + /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + { /* zName: */ "lock_status", + /* ePragTyp: */ PragTyp_LOCK_STATUS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "locking_mode", + /* ePragTyp: */ PragTyp_LOCKING_MODE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "max_page_count", + /* ePragTyp: */ PragTyp_PAGE_COUNT, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "mmap_size", + /* ePragTyp: */ PragTyp_MMAP_SIZE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "page_count", + /* ePragTyp: */ PragTyp_PAGE_COUNT, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "page_size", + /* ePragTyp: */ PragTyp_PAGE_SIZE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE) + { /* zName: */ "parser_trace", + /* ePragTyp: */ PragTyp_PARSER_TRACE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "query_only", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_QueryOnly }, +#endif +#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) + { /* zName: */ "quick_check", + /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "read_uncommitted", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ReadUncommitted }, + { /* zName: */ "recursive_triggers", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_RecTriggers }, +#endif +#if defined(SQLITE_HAS_CODEC) + { /* zName: */ "rekey", + /* ePragTyp: */ PragTyp_REKEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "reverse_unordered_selects", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ReverseOrder }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "schema_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ 0, + /* iArg: */ BTREE_SCHEMA_VERSION }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "secure_delete", + /* ePragTyp: */ PragTyp_SECURE_DELETE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "short_column_names", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ShortColNames }, +#endif + { /* zName: */ "shrink_memory", + /* ePragTyp: */ PragTyp_SHRINK_MEMORY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "soft_heap_limit", + /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if defined(SQLITE_DEBUG) + { /* zName: */ "sql_trace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_SqlTrace }, +#endif +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "stats", + /* ePragTyp: */ PragTyp_STATS, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "synchronous", + /* ePragTyp: */ PragTyp_SYNCHRONOUS, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "table_info", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "temp_store", + /* ePragTyp: */ PragTyp_TEMP_STORE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "temp_store_directory", + /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif + { /* zName: */ "threads", + /* ePragTyp: */ PragTyp_THREADS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "user_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ 0, + /* iArg: */ BTREE_USER_VERSION }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if defined(SQLITE_DEBUG) + { /* zName: */ "vdbe_addoptrace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeAddopTrace }, + { /* zName: */ "vdbe_debug", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, + { /* zName: */ "vdbe_eqp", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeEQP }, + { /* zName: */ "vdbe_listing", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeListing }, + { /* zName: */ "vdbe_trace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeTrace }, +#endif +#endif +#if !defined(SQLITE_OMIT_WAL) + { /* zName: */ "wal_autocheckpoint", + /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "wal_checkpoint", + /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "writable_schema", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, +#endif +}; +/* Number of pragmas: 60 on by default, 73 total. */ /************** End of pragma.h **********************************************/ /************** Continuing where we left off in pragma.c *********************/ /* @@ -113121,45 +111686,47 @@ return SQLITE_OK; } #endif /* SQLITE_PAGER_PRAGMAS */ /* -** Set result column names for a pragma. +** Set the names of the first N columns to the values in azCol[] */ -static void setPragmaResultColumnNames( - Vdbe *v, /* The query under construction */ - const PragmaName *pPragma /* The pragma */ +static void setAllColumnNames( + Vdbe *v, /* The query under construction */ + int N, /* Number of columns */ + const char **azCol /* Names of columns */ ){ - u8 n = pPragma->nPragCName; - sqlite3VdbeSetNumCols(v, n==0 ? 1 : n); - if( n==0 ){ - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC); - }else{ - int i, j; - for(i=0, j=pPragma->iPragCName; iupr ? 0 : &aPragmaName[mid]; -} - -/* -** Helper subroutine for PRAGMA integrity_check: -** -** Generate code to output a single-column result row with the result -** held in register regResult. Decrement the result count and halt if -** the maximum number of result rows have been issued. -*/ -static int integrityCheckResultRow(Vdbe *v, int regResult){ - int addr; - sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1); - addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); - return addr; -} - /* ** Process a pragma statement. ** ** Pragmas are of this form: ** @@ -113297,15 +111828,16 @@ char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ const char *zDb = 0; /* The database name */ Token *pId; /* Pointer to token */ char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ int iDb; /* Database index for */ + int lwr, upr, mid = 0; /* Binary search bounds */ int rc; /* return value form SQLITE_FCNTL_PRAGMA */ sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ - const PragmaName *pPragma; /* The pragma */ + const struct sPragmaNames *pPragma; if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; @@ -113356,13 +111888,11 @@ aFcntl[2] = zRight; aFcntl[3] = 0; db->busyHandler.nBusy = 0; rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); if( rc==SQLITE_OK ){ - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT); - returnSingleText(v, aFcntl[0]); + returnSingleText(v, "result", aFcntl[0]); sqlite3_free(aFcntl[0]); goto pragma_out; } if( rc!=SQLITE_NOTFOUND ){ if( aFcntl[0] ){ @@ -113373,25 +111903,30 @@ pParse->rc = rc; goto pragma_out; } /* Locate the pragma in the lookup table */ - pPragma = pragmaLocate(zLeft); - if( pPragma==0 ) goto pragma_out; + lwr = 0; + upr = ArraySize(aPragmaNames)-1; + while( lwr<=upr ){ + mid = (lwr+upr)/2; + rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName); + if( rc==0 ) break; + if( rc<0 ){ + upr = mid - 1; + }else{ + lwr = mid + 1; + } + } + if( lwr>upr ) goto pragma_out; + pPragma = &aPragmaNames[mid]; /* Make sure the database schema is loaded if the pragma requires that */ - if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){ + if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; } - /* Register the result column names for pragmas that return results */ - if( (pPragma->mPragFlg & PragFlg_NoColumns)==0 - && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0) - ){ - setPragmaResultColumnNames(v, pPragma); - } - /* Jump to the appropriate pragma handler */ switch( pPragma->ePragTyp ){ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* @@ -113424,10 +111959,11 @@ { OP_ResultRow, 1, 1, 0}, }; VdbeOp *aOp; sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ + setOneColumnName(v, "cache_size"); pParse->nMem += 2; sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize)); aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn); if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; aOp[0].p1 = iDb; @@ -113458,11 +111994,11 @@ case PragTyp_PAGE_SIZE: { Btree *pBt = pDb->pBt; assert( pBt!=0 ); if( !zRight ){ int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0; - returnSingleInt(v, size); + returnSingleInt(v, "page_size", size); }else{ /* Malloc may fail when setting the page-size, as there is an internal ** buffer that the pager module resizes using sqlite3_realloc(). */ db->nextPagesize = sqlite3Atoi(zRight); @@ -113493,11 +112029,11 @@ for(ii=0; iinDb; ii++){ sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b); } } b = sqlite3BtreeSecureDelete(pBt, b); - returnSingleInt(v, b); + returnSingleInt(v, "secure_delete", b); break; } /* ** PRAGMA [schema.]max_page_count @@ -113525,10 +112061,12 @@ }else{ sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, sqlite3AbsInt32(sqlite3Atoi(zRight))); } sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); break; } /* ** PRAGMA [schema.]locking_mode @@ -113570,11 +112108,11 @@ assert( eMode==PAGER_LOCKINGMODE_NORMAL || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ zRet = "exclusive"; } - returnSingleText(v, zRet); + returnSingleText(v, "locking_mode", zRet); break; } /* ** PRAGMA [schema.]journal_mode @@ -113583,10 +112121,11 @@ */ case PragTyp_JOURNAL_MODE: { int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ int ii; /* Loop counter */ + setOneColumnName(v, "journal_mode"); if( zRight==0 ){ /* If there is no "=MODE" part of the pragma, do a query for the ** current mode */ eMode = PAGER_JOURNALMODE_QUERY; }else{ @@ -113628,11 +112167,11 @@ if( zRight ){ sqlite3DecOrHexToI64(zRight, &iLimit); if( iLimit<-1 ) iLimit = -1; } iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit); - returnSingleInt(v, iLimit); + returnSingleInt(v, "journal_size_limit", iLimit); break; } #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ @@ -113646,11 +112185,11 @@ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_AUTO_VACUUM: { Btree *pBt = pDb->pBt; assert( pBt!=0 ); if( !zRight ){ - returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt)); + returnSingleInt(v, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt)); }else{ int eAuto = getAutoVacuum(zRight); assert( eAuto>=0 && eAuto<=2 ); db->nextAutovac = (u8)eAuto; /* Call SetAutoVacuum() to set initialize the internal auto and @@ -113725,11 +112264,11 @@ ** of memory. */ case PragTyp_CACHE_SIZE: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ - returnSingleInt(v, pDb->pSchema->cache_size); + returnSingleInt(v, "cache_size", pDb->pSchema->cache_size); }else{ int size = sqlite3Atoi(zRight); pDb->pSchema->cache_size = size; sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); } @@ -113759,11 +112298,11 @@ ** not just the schema specified. */ case PragTyp_CACHE_SPILL: { assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ - returnSingleInt(v, + returnSingleInt(v, "cache_spill", (db->flags & SQLITE_CacheSpill)==0 ? 0 : sqlite3BtreeSetSpillSize(pDb->pBt,0)); }else{ int size = 1; if( sqlite3GetInt32(zRight, &size) ){ @@ -113813,11 +112352,11 @@ #else sz = 0; rc = SQLITE_OK; #endif if( rc==SQLITE_OK ){ - returnSingleInt(v, sz); + returnSingleInt(v, "mmap_size", sz); }else if( rc!=SQLITE_NOTFOUND ){ pParse->nErr++; pParse->rc = rc; } break; @@ -113834,11 +112373,11 @@ ** Note that it is possible for the library compile-time options to ** override this setting */ case PragTyp_TEMP_STORE: { if( !zRight ){ - returnSingleInt(v, db->temp_store); + returnSingleInt(v, "temp_store", db->temp_store); }else{ changeTempStorage(pParse, zRight); } break; } @@ -113853,11 +112392,11 @@ ** If temporary directory is changed, then invalidateTempStorage. ** */ case PragTyp_TEMP_STORE_DIRECTORY: { if( !zRight ){ - returnSingleText(v, sqlite3_temp_directory); + returnSingleText(v, "temp_store_directory", sqlite3_temp_directory); }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ int res; rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); @@ -113897,11 +112436,11 @@ ** by this setting, regardless of its value. ** */ case PragTyp_DATA_STORE_DIRECTORY: { if( !zRight ){ - returnSingleText(v, sqlite3_data_directory); + returnSingleText(v, "data_store_directory", sqlite3_data_directory); }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ int res; rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); @@ -113936,11 +112475,11 @@ Pager *pPager = sqlite3BtreePager(pDb->pBt); char *proxy_file_path = NULL; sqlite3_file *pFile = sqlite3PagerFile(pPager); sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE, &proxy_file_path); - returnSingleText(v, proxy_file_path); + returnSingleText(v, "lock_proxy_file", proxy_file_path); }else{ Pager *pPager = sqlite3BtreePager(pDb->pBt); sqlite3_file *pFile = sqlite3PagerFile(pPager); int res; if( zRight[0] ){ @@ -113968,16 +112507,16 @@ ** default value will be restored the next time the database is ** opened. */ case PragTyp_SYNCHRONOUS: { if( !zRight ){ - returnSingleInt(v, pDb->safety_level-1); + returnSingleInt(v, "synchronous", pDb->safety_level-1); }else{ if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); - }else if( iDb!=1 ){ + }else{ int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; if( iLevel==0 ) iLevel = 1; pDb->safety_level = iLevel; pDb->bSyncSet = 1; setAllPagerFlags(db); @@ -113988,12 +112527,11 @@ #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ #ifndef SQLITE_OMIT_FLAG_PRAGMAS case PragTyp_FLAG: { if( zRight==0 ){ - setPragmaResultColumnNames(v, pPragma); - returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); + returnSingleInt(v, pPragma->zName, (db->flags & pPragma->iArg)!=0 ); }else{ int mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ @@ -114039,16 +112577,20 @@ */ case PragTyp_TABLE_INFO: if( zRight ){ Table *pTab; pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ + static const char *azCol[] = { + "cid", "name", "type", "notnull", "dflt_value", "pk" + }; int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); + setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) ); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ if( IsHiddenColumn(pCol) ){ nHidden++; continue; @@ -114072,43 +112614,45 @@ } } } break; -#ifdef SQLITE_DEBUG case PragTyp_STATS: { + static const char *azCol[] = { "table", "index", "width", "height" }; Index *pIdx; HashElem *i; - pParse->nMem = 5; + v = sqlite3GetVdbe(pParse); + pParse->nMem = 4; sqlite3CodeVerifySchema(pParse, iDb); + setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) ); for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); - sqlite3VdbeMultiLoad(v, 1, "ssiii", + sqlite3VdbeMultiLoad(v, 1, "ssii", pTab->zName, 0, pTab->szTabRow, - pTab->nRowLogEst, - pTab->tabFlags); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); + pTab->nRowLogEst); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - sqlite3VdbeMultiLoad(v, 2, "siii", + sqlite3VdbeMultiLoad(v, 2, "sii", pIdx->zName, pIdx->szIdxRow, - pIdx->aiRowLogEst[0], - pIdx->hasStat1); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); + pIdx->aiRowLogEst[0]); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4); } } } break; -#endif case PragTyp_INDEX_INFO: if( zRight ){ Index *pIdx; Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ + static const char *azCol[] = { + "seqno", "cid", "name", "desc", "coll", "key" + }; int i; int mx; if( pPragma->iArg ){ /* PRAGMA index_xinfo (newer version with more rows and columns) */ mx = pIdx->nColumn; @@ -114118,11 +112662,12 @@ mx = pIdx->nKeyCol; pParse->nMem = 3; } pTab = pIdx->pTable; sqlite3CodeVerifySchema(pParse, iDb); - assert( pParse->nMem<=pPragma->nPragCName ); + assert( pParse->nMem<=ArraySize(azCol) ); + setAllColumnNames(v, pParse->nMem, azCol); for(i=0; iaiColumn[i]; sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum, cnum<0 ? 0 : pTab->aCol[cnum].zName); if( pPragma->iArg ){ @@ -114141,12 +112686,17 @@ Index *pIdx; Table *pTab; int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ + static const char *azCol[] = { + "seq", "name", "unique", "origin", "partial" + }; + v = sqlite3GetVdbe(pParse); pParse->nMem = 5; sqlite3CodeVerifySchema(pParse, iDb); + setAllColumnNames(v, 5, azCol); assert( 5==ArraySize(azCol) ); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeMultiLoad(v, 1, "isisi", i, pIdx->zName, @@ -114158,12 +112708,14 @@ } } break; case PragTyp_DATABASE_LIST: { + static const char *azCol[] = { "seq", "name", "file" }; int i; pParse->nMem = 3; + setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zDbSName!=0 ); sqlite3VdbeMultiLoad(v, 1, "iss", i, @@ -114173,13 +112725,15 @@ } } break; case PragTyp_COLLATION_LIST: { + static const char *azCol[] = { "seq", "name" }; int i = 0; HashElem *p; pParse->nMem = 2; + setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) ); for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } @@ -114191,15 +112745,21 @@ case PragTyp_FOREIGN_KEY_LIST: if( zRight ){ FKey *pFK; Table *pTab; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ + v = sqlite3GetVdbe(pParse); pFK = pTab->pFKey; if( pFK ){ + static const char *azCol[] = { + "id", "seq", "table", "from", "to", "on_update", "on_delete", + "match" + }; int i = 0; pParse->nMem = 8; sqlite3CodeVerifySchema(pParse, iDb); + setAllColumnNames(v, 8, azCol); assert( 8==ArraySize(azCol) ); while(pFK){ int j; for(j=0; jnCol; j++){ sqlite3VdbeMultiLoad(v, 1, "iissssss", i, @@ -114236,15 +112796,18 @@ int regKey; /* Register to hold key for checking the FK */ int regRow; /* Registers to hold a row from pTab */ int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ int *aiCols; /* child to parent column mapping */ + static const char *azCol[] = { "table", "rowid", "parent", "fkid" }; regResult = pParse->nMem+1; pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; + v = sqlite3GetVdbe(pParse); + setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) ); sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); @@ -114355,21 +112918,13 @@ #ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX # define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 #endif #ifndef SQLITE_OMIT_INTEGRITY_CHECK - /* PRAGMA integrity_check - ** PRAGMA integrity_check(N) - ** PRAGMA quick_check - ** PRAGMA quick_check(N) - ** - ** Verify the integrity of the database. - ** - ** The "quick_check" is reduced version of + /* Pragma "quick_check" is reduced version of ** integrity_check designed to detect most database corruption - ** without the overhead of cross-checking indexes. Quick_check - ** is linear time wherease integrity_check is O(NlogN). + ** without most of the overhead of a full integrity-check. */ case PragTyp_INTEGRITY_CHECK: { int i, j, addr, mxErr; int isQuick = (sqlite3Tolower(zLeft[0])=='q'); @@ -114387,20 +112942,21 @@ assert( iDb==0 || pId2->z ); if( pId2->z==0 ) iDb = -1; /* Initialize the VDBE program */ pParse->nMem = 6; + setOneColumnName(v, "integrity_check"); /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; if( zRight ){ sqlite3GetInt32(zRight, &mxErr); if( mxErr<=0 ){ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; } } - sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */ + sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ /* Do an integrity check on each database file */ for(i=0; inDb; i++){ HashElem *x; Hash *pTbls; @@ -114411,10 +112967,14 @@ if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; sqlite3CodeVerifySchema(pParse, i); + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); /* Do an integrity check of the B-Tree ** ** Begin by finding the root pages numbers ** for all tables and indices in the database. @@ -114450,31 +113010,29 @@ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), P4_DYNAMIC); sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); - integrityCheckResultRow(v, 2); + sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); sqlite3VdbeJumpHere(v, addr); /* Make sure all the indices are constructed correctly. */ - for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx, *pPk; Index *pPrior = 0; int loopTop; int iDataCur, iIdxCur; int r1 = -1; - if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */ - if( pTab->pCheck==0 - && (pTab->tabFlags & TF_HasNotNull)==0 - && (pTab->pIndex==0 || isQuick) - ){ - continue; /* No additional checks needed for this table */ - } + if( pTab->pIndex==0 ) continue; pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); sqlite3ExprCacheClear(pParse); sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0, 1, 0, &iDataCur, &iIdxCur); sqlite3VdbeAddOp2(v, OP_Integer, 0, 7); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ @@ -114485,46 +113043,28 @@ sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v); loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1); /* Verify that all NOT NULL columns really are NOT NULL */ for(j=0; jnCol; j++){ char *zErr; - int jmp2; + int jmp2, jmp3; if( j==pTab->iPKey ) continue; if( pTab->aCol[j].notNull==0 ) continue; sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, pTab->aCol[j].zName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v, 3); + sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); + jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); + sqlite3VdbeAddOp0(v, OP_Halt); sqlite3VdbeJumpHere(v, jmp2); - } - /* Verify CHECK constraints */ - if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ - int addrCkFault = sqlite3VdbeMakeLabel(v); - int addrCkOk = sqlite3VdbeMakeLabel(v); - ExprList *pCheck = pTab->pCheck; - char *zErr; - int k; - pParse->iSelfTab = iDataCur; - sqlite3ExprCachePush(pParse); - for(k=pCheck->nExpr-1; k>0; k--){ - sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0); - } - sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk, - SQLITE_JUMPIFNULL); - sqlite3VdbeResolveLabel(v, addrCkFault); - zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s", - pTab->zName); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v, 3); - sqlite3VdbeResolveLabel(v, addrCkOk); - sqlite3ExprCachePop(pParse); + sqlite3VdbeJumpHere(v, jmp3); } /* Validate index entries for the current row */ - for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2, jmp3, jmp4, jmp5; int ckUniq = sqlite3VdbeMakeLabel(v); if( pPk==pIdx ) continue; r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3, pPrior, r1); @@ -114531,17 +113071,20 @@ pPrior = pIdx; sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */ /* Verify that an index entry exists for the current table row */ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1, pIdx->nColumn); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ sqlite3VdbeLoadString(v, 3, "row "); sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3); sqlite3VdbeLoadString(v, 4, " missing from index "); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); - jmp4 = integrityCheckResultRow(v, 3); + sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1); + jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v); + sqlite3VdbeAddOp0(v, OP_Halt); sqlite3VdbeJumpHere(v, jmp2); /* For UNIQUE indexes, verify that only one entry exists with the ** current key. The entry is unique if (1) any column is NULL ** or (2) the next entry has a different key */ if( IsUniqueIndex(pIdx) ){ @@ -114558,10 +113101,11 @@ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v); sqlite3VdbeGoto(v, uniqOk); sqlite3VdbeJumpHere(v, jmp6); sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1, pIdx->nKeyCol); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */ sqlite3VdbeLoadString(v, 3, "non-unique entry in index "); sqlite3VdbeGoto(v, jmp5); sqlite3VdbeResolveLabel(v, uniqOk); } sqlite3VdbeJumpHere(v, jmp4); @@ -114568,39 +113112,40 @@ sqlite3ResolvePartIdxLabel(pParse, jmp3); } sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v); sqlite3VdbeJumpHere(v, loopTop-1); #ifndef SQLITE_OMIT_BTREECOUNT - if( !isQuick ){ - sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); - for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ - if( pPk==pIdx ) continue; - sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); - addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v); - sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); - sqlite3VdbeLoadString(v, 3, pIdx->zName); - sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); - integrityCheckResultRow(v, 7); - sqlite3VdbeJumpHere(v, addr); - } + sqlite3VdbeLoadString(v, 2, "wrong # of entries in index "); + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + if( pPk==pIdx ) continue; + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3); + sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NOTNULL); + sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); + sqlite3VdbeLoadString(v, 3, pIdx->zName); + sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7); + sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1); } #endif /* SQLITE_OMIT_BTREECOUNT */ } } { static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList endCode[] = { { OP_AddImm, 1, 0, 0}, /* 0 */ - { OP_IfNotZero, 1, 4, 0}, /* 1 */ + { OP_If, 1, 4, 0}, /* 1 */ { OP_String8, 0, 3, 0}, /* 2 */ { OP_ResultRow, 3, 1, 0}, /* 3 */ }; VdbeOp *aOp; aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn); if( aOp ){ - aOp[0].p2 = 1-mxErr; + aOp[0].p2 = -mxErr; aOp[2].p4type = P4_STATIC; aOp[2].p4.z = "ok"; } } } @@ -114649,11 +113194,11 @@ if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 ); assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE ); assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE ); - returnSingleText(v, encnames[ENC(pParse->db)].zName); + returnSingleText(v, "encoding", encnames[ENC(pParse->db)].zName); }else{ /* "PRAGMA encoding = XXX" */ /* Only change the value of sqlite.enc if the database handle is not ** initialized. If the main database exists, the new sqlite.enc value ** will be overwritten when the schema is next loaded. If it does not ** already exists, it will be created to use the new encoding value. @@ -114712,11 +113257,11 @@ ** applications for any purpose. */ case PragTyp_HEADER_VALUE: { int iCookie = pPragma->iArg; /* Which cookie to read or write */ sqlite3VdbeUsesBtree(v, iDb); - if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){ + if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ { OP_SetCookie, 0, 0, 0}, /* 1 */ }; @@ -114740,10 +113285,12 @@ aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie),readCookie,0); if( ONLY_IF_REALLOC_STRESS(aOp==0) ) break; aOp[0].p1 = iDb; aOp[1].p1 = iDb; aOp[1].p3 = iCookie; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); sqlite3VdbeReusable(v); } } break; #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ @@ -114757,10 +113304,11 @@ */ case PragTyp_COMPILE_OPTIONS: { int i = 0; const char *zOpt; pParse->nMem = 1; + setOneColumnName(v, "compile_option"); while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){ sqlite3VdbeLoadString(v, 1, zOpt); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } sqlite3VdbeReusable(v); @@ -114773,10 +113321,11 @@ ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate ** ** Checkpoint the database. */ case PragTyp_WAL_CHECKPOINT: { + static const char *azCol[] = { "busy", "log", "checkpointed" }; int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED); int eMode = SQLITE_CHECKPOINT_PASSIVE; if( zRight ){ if( sqlite3StrICmp(zRight, "full")==0 ){ eMode = SQLITE_CHECKPOINT_FULL; @@ -114784,10 +113333,11 @@ eMode = SQLITE_CHECKPOINT_RESTART; }else if( sqlite3StrICmp(zRight, "truncate")==0 ){ eMode = SQLITE_CHECKPOINT_TRUNCATE; } } + setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); pParse->nMem = 3; sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } break; @@ -114802,11 +113352,11 @@ */ case PragTyp_WAL_AUTOCHECKPOINT: { if( zRight ){ sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, + returnSingleInt(v, "wal_autocheckpoint", db->xWalCallback==sqlite3WalDefaultHook ? SQLITE_PTR_TO_INT(db->pWalArg) : 0); } break; #endif @@ -114821,122 +113371,10 @@ case PragTyp_SHRINK_MEMORY: { sqlite3_db_release_memory(db); break; } - /* - ** PRAGMA optimize - ** PRAGMA optimize(MASK) - ** PRAGMA schema.optimize - ** PRAGMA schema.optimize(MASK) - ** - ** Attempt to optimize the database. All schemas are optimized in the first - ** two forms, and only the specified schema is optimized in the latter two. - ** - ** The details of optimizations performed by this pragma are expected - ** to change and improve over time. Applications should anticipate that - ** this pragma will perform new optimizations in future releases. - ** - ** The optional argument is a bitmask of optimizations to perform: - ** - ** 0x0001 Debugging mode. Do not actually perform any optimizations - ** but instead return one line of text for each optimization - ** that would have been done. Off by default. - ** - ** 0x0002 Run ANALYZE on tables that might benefit. On by default. - ** See below for additional information. - ** - ** 0x0004 (Not yet implemented) Record usage and performance - ** information from the current session in the - ** database file so that it will be available to "optimize" - ** pragmas run by future database connections. - ** - ** 0x0008 (Not yet implemented) Create indexes that might have - ** been helpful to recent queries - ** - ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all ** of the optimizations listed above except Debug Mode, including new - ** optimizations that have not yet been invented. If new optimizations are - ** ever added that should be off by default, those off-by-default - ** optimizations will have bitmasks of 0x10000 or larger. - ** - ** DETERMINATION OF WHEN TO RUN ANALYZE - ** - ** In the current implementation, a table is analyzed if only if all of - ** the following are true: - ** - ** (1) MASK bit 0x02 is set. - ** - ** (2) The query planner used sqlite_stat1-style statistics for one or - ** more indexes of the table at some point during the lifetime of - ** the current connection. - ** - ** (3) One or more indexes of the table are currently unanalyzed OR - ** the number of rows in the table has increased by 25 times or more - ** since the last time ANALYZE was run. - ** - ** The rules for when tables are analyzed are likely to change in - ** future releases. - */ - case PragTyp_OPTIMIZE: { - int iDbLast; /* Loop termination point for the schema loop */ - int iTabCur; /* Cursor for a table whose size needs checking */ - HashElem *k; /* Loop over tables of a schema */ - Schema *pSchema; /* The current schema */ - Table *pTab; /* A table in the schema */ - Index *pIdx; /* An index of the table */ - LogEst szThreshold; /* Size threshold above which reanalysis is needd */ - char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ - u32 opMask; /* Mask of operations to perform */ - - if( zRight ){ - opMask = (u32)sqlite3Atoi(zRight); - if( (opMask & 0x02)==0 ) break; - }else{ - opMask = 0xfffe; - } - iTabCur = pParse->nTab++; - for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){ - if( iDb==1 ) continue; - sqlite3CodeVerifySchema(pParse, iDb); - pSchema = db->aDb[iDb].pSchema; - for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ - pTab = (Table*)sqliteHashData(k); - - /* If table pTab has not been used in a way that would benefit from - ** having analysis statistics during the current session, then skip it. - ** This also has the effect of skipping virtual tables and views */ - if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue; - - /* Reanalyze if the table is 25 times larger than the last analysis */ - szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 ); - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( !pIdx->hasStat1 ){ - szThreshold = 0; /* Always analyze if any index lacks statistics */ - break; - } - } - if( szThreshold ){ - sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); - sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur, - sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold); - VdbeCoverage(v); - } - zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"", - db->aDb[iDb].zDbSName, pTab->zName); - if( opMask & 0x01 ){ - int r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1); - }else{ - sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC); - } - } - } - sqlite3VdbeAddOp0(v, OP_Expire); - break; - } - /* ** PRAGMA busy_timeout ** PRAGMA busy_timeout = N ** ** Call sqlite3_busy_timeout(db, N). Return the current timeout value @@ -114947,11 +113385,11 @@ /*case PragTyp_BUSY_TIMEOUT*/ default: { assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT ); if( zRight ){ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } - returnSingleInt(v, db->busyTimeout); + returnSingleInt(v, "timeout", db->busyTimeout); break; } /* ** PRAGMA soft_heap_limit @@ -114967,11 +113405,11 @@ case PragTyp_SOFT_HEAP_LIMIT: { sqlite3_int64 N; if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){ sqlite3_soft_heap_limit64(N); } - returnSingleInt(v, sqlite3_soft_heap_limit64(-1)); + returnSingleInt(v, "soft_heap_limit", sqlite3_soft_heap_limit64(-1)); break; } /* ** PRAGMA threads @@ -114986,11 +113424,12 @@ && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK && N>=0 ){ sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff)); } - returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); + returnSingleInt(v, "threads", + sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1)); break; } #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* @@ -114998,11 +113437,13 @@ */ case PragTyp_LOCK_STATUS: { static const char *const azLockName[] = { "unlocked", "shared", "reserved", "pending", "exclusive" }; + static const char *azCol[] = { "database", "status" }; int i; + setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) ); pParse->nMem = 2; for(i=0; inDb; i++){ Btree *pBt; const char *zState = "unknown"; int j; @@ -115064,329 +113505,14 @@ break; #endif } /* End of the PRAGMA switch */ - /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only - ** purpose is to execute assert() statements to verify that if the - ** PragFlg_NoColumns1 flag is set and the caller specified an argument - ** to the PRAGMA, the implementation has not added any OP_ResultRow - ** instructions to the VM. */ - if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){ - sqlite3VdbeVerifyNoResultRow(v); - } - pragma_out: sqlite3DbFree(db, zLeft); sqlite3DbFree(db, zRight); } -#ifndef SQLITE_OMIT_VIRTUALTABLE -/***************************************************************************** -** Implementation of an eponymous virtual table that runs a pragma. -** -*/ -typedef struct PragmaVtab PragmaVtab; -typedef struct PragmaVtabCursor PragmaVtabCursor; -struct PragmaVtab { - sqlite3_vtab base; /* Base class. Must be first */ - sqlite3 *db; /* The database connection to which it belongs */ - const PragmaName *pName; /* Name of the pragma */ - u8 nHidden; /* Number of hidden columns */ - u8 iHidden; /* Index of the first hidden column */ -}; -struct PragmaVtabCursor { - sqlite3_vtab_cursor base; /* Base class. Must be first */ - sqlite3_stmt *pPragma; /* The pragma statement to run */ - sqlite_int64 iRowid; /* Current rowid */ - char *azArg[2]; /* Value of the argument and schema */ -}; - -/* -** Pragma virtual table module xConnect method. -*/ -static int pragmaVtabConnect( - sqlite3 *db, - void *pAux, - int argc, const char *const*argv, - sqlite3_vtab **ppVtab, - char **pzErr -){ - const PragmaName *pPragma = (const PragmaName*)pAux; - PragmaVtab *pTab = 0; - int rc; - int i, j; - char cSep = '('; - StrAccum acc; - char zBuf[200]; - - UNUSED_PARAMETER(argc); - UNUSED_PARAMETER(argv); - sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); - sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x"); - for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){ - sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]); - cSep = ','; - } - if( i==0 ){ - sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName); - cSep = ','; - i++; - } - j = 0; - if( pPragma->mPragFlg & PragFlg_Result1 ){ - sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN"); - j++; - } - if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){ - sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN"); - j++; - } - sqlite3StrAccumAppend(&acc, ")", 1); - sqlite3StrAccumFinish(&acc); - assert( strlen(zBuf) < sizeof(zBuf)-1 ); - rc = sqlite3_declare_vtab(db, zBuf); - if( rc==SQLITE_OK ){ - pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab)); - if( pTab==0 ){ - rc = SQLITE_NOMEM; - }else{ - memset(pTab, 0, sizeof(PragmaVtab)); - pTab->pName = pPragma; - pTab->db = db; - pTab->iHidden = i; - pTab->nHidden = j; - } - }else{ - *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); - } - - *ppVtab = (sqlite3_vtab*)pTab; - return rc; -} - -/* -** Pragma virtual table module xDisconnect method. -*/ -static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){ - PragmaVtab *pTab = (PragmaVtab*)pVtab; - sqlite3_free(pTab); - return SQLITE_OK; -} - -/* Figure out the best index to use to search a pragma virtual table. -** -** There are not really any index choices. But we want to encourage the -** query planner to give == constraints on as many hidden parameters as -** possible, and especially on the first hidden parameter. So return a -** high cost if hidden parameters are unconstrained. -*/ -static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ - PragmaVtab *pTab = (PragmaVtab*)tab; - const struct sqlite3_index_constraint *pConstraint; - int i, j; - int seen[2]; - - pIdxInfo->estimatedCost = (double)1; - if( pTab->nHidden==0 ){ return SQLITE_OK; } - pConstraint = pIdxInfo->aConstraint; - seen[0] = 0; - seen[1] = 0; - for(i=0; inConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pConstraint->iColumn < pTab->iHidden ) continue; - j = pConstraint->iColumn - pTab->iHidden; - assert( j < 2 ); - seen[j] = i+1; - } - if( seen[0]==0 ){ - pIdxInfo->estimatedCost = (double)2147483647; - pIdxInfo->estimatedRows = 2147483647; - return SQLITE_OK; - } - j = seen[0]-1; - pIdxInfo->aConstraintUsage[j].argvIndex = 1; - pIdxInfo->aConstraintUsage[j].omit = 1; - if( seen[1]==0 ) return SQLITE_OK; - pIdxInfo->estimatedCost = (double)20; - pIdxInfo->estimatedRows = 20; - j = seen[1]-1; - pIdxInfo->aConstraintUsage[j].argvIndex = 2; - pIdxInfo->aConstraintUsage[j].omit = 1; - return SQLITE_OK; -} - -/* Create a new cursor for the pragma virtual table */ -static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){ - PragmaVtabCursor *pCsr; - pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr)); - if( pCsr==0 ) return SQLITE_NOMEM; - memset(pCsr, 0, sizeof(PragmaVtabCursor)); - pCsr->base.pVtab = pVtab; - *ppCursor = &pCsr->base; - return SQLITE_OK; -} - -/* Clear all content from pragma virtual table cursor. */ -static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){ - int i; - sqlite3_finalize(pCsr->pPragma); - pCsr->pPragma = 0; - for(i=0; iazArg); i++){ - sqlite3_free(pCsr->azArg[i]); - pCsr->azArg[i] = 0; - } -} - -/* Close a pragma virtual table cursor */ -static int pragmaVtabClose(sqlite3_vtab_cursor *cur){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur; - pragmaVtabCursorClear(pCsr); - sqlite3_free(pCsr); - return SQLITE_OK; -} - -/* Advance the pragma virtual table cursor to the next row */ -static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - int rc = SQLITE_OK; - - /* Increment the xRowid value */ - pCsr->iRowid++; - assert( pCsr->pPragma ); - if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){ - rc = sqlite3_finalize(pCsr->pPragma); - pCsr->pPragma = 0; - pragmaVtabCursorClear(pCsr); - } - return rc; -} - -/* -** Pragma virtual table module xFilter method. -*/ -static int pragmaVtabFilter( - sqlite3_vtab_cursor *pVtabCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv -){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); - int rc; - int i, j; - StrAccum acc; - char *zSql; - - UNUSED_PARAMETER(idxNum); - UNUSED_PARAMETER(idxStr); - pragmaVtabCursorClear(pCsr); - j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1; - for(i=0; iazArg) ); - pCsr->azArg[j] = sqlite3_mprintf("%s", sqlite3_value_text(argv[i])); - if( pCsr->azArg[j]==0 ){ - return SQLITE_NOMEM; - } - } - sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]); - sqlite3StrAccumAppendAll(&acc, "PRAGMA "); - if( pCsr->azArg[1] ){ - sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]); - } - sqlite3StrAccumAppendAll(&acc, pTab->pName->zName); - if( pCsr->azArg[0] ){ - sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]); - } - zSql = sqlite3StrAccumFinish(&acc); - if( zSql==0 ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0); - sqlite3_free(zSql); - if( rc!=SQLITE_OK ){ - pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); - return rc; - } - return pragmaVtabNext(pVtabCursor); -} - -/* -** Pragma virtual table module xEof method. -*/ -static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - return (pCsr->pPragma==0); -} - -/* The xColumn method simply returns the corresponding column from -** the PRAGMA. -*/ -static int pragmaVtabColumn( - sqlite3_vtab_cursor *pVtabCursor, - sqlite3_context *ctx, - int i -){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab); - if( iiHidden ){ - sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i)); - }else{ - sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT); - } - return SQLITE_OK; -} - -/* -** Pragma virtual table module xRowid method. -*/ -static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){ - PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor; - *p = pCsr->iRowid; - return SQLITE_OK; -} - -/* The pragma virtual table object */ -static const sqlite3_module pragmaVtabModule = { - 0, /* iVersion */ - 0, /* xCreate - create a table */ - pragmaVtabConnect, /* xConnect - connect to an existing table */ - pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */ - pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */ - 0, /* xDestroy - Drop a table */ - pragmaVtabOpen, /* xOpen - open a cursor */ - pragmaVtabClose, /* xClose - close a cursor */ - pragmaVtabFilter, /* xFilter - configure scan constraints */ - pragmaVtabNext, /* xNext - advance a cursor */ - pragmaVtabEof, /* xEof */ - pragmaVtabColumn, /* xColumn - read data */ - pragmaVtabRowid, /* xRowid - read data */ - 0, /* xUpdate - write data */ - 0, /* xBegin - begin transaction */ - 0, /* xSync - sync transaction */ - 0, /* xCommit - commit transaction */ - 0, /* xRollback - rollback transaction */ - 0, /* xFindFunction - function overloading */ - 0, /* xRename - rename the table */ - 0, /* xSavepoint */ - 0, /* xRelease */ - 0 /* xRollbackTo */ -}; - -/* -** Check to see if zTabName is really the name of a pragma. If it is, -** then register an eponymous virtual table for that pragma and return -** a pointer to the Module object for the new virtual table. -*/ -SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){ - const PragmaName *pName; - assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 ); - pName = pragmaLocate(zName+7); - if( pName==0 ) return 0; - if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0; - assert( sqlite3HashFind(&db->aModule, zName)==0 ); - return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0); -} - -#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_PRAGMA */ /************** End of pragma.c **********************************************/ /************** Begin file prepare.c *****************************************/ @@ -116579,11 +114705,11 @@ assert( pSrc->a[iRight].pTab ); pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft); pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight); - pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); + pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0); if( pEq && isOuterJoin ){ ExprSetProperty(pEq, EP_FromJoin); assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(pEq, EP_NoReduce); pEq->iRightJoinTable = (i16)pE2->iTable; @@ -116766,11 +114892,11 @@ int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ int op; /* Opcode to add sorter record to sorter */ int iLimit; /* LIMIT counter */ assert( bSeq==0 || bSeq==1 ); - assert( nData==1 || regData==regOrigData || regOrigData==0 ); + assert( nData==1 || regData==regOrigData ); if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); regBase = regData - nExpr - bSeq; }else{ regBase = pParse->nMem + 1; @@ -116778,15 +114904,15 @@ } assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; pSort->labelDone = sqlite3VdbeMakeLabel(v); sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, - SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0)); + SQLITE_ECEL_DUP|SQLITE_ECEL_REF); if( bSeq ){ sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); } - if( nPrefixReg==0 && nData>0 ){ + if( nPrefixReg==0 ){ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); } sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ @@ -116832,20 +114958,19 @@ if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; }else{ op = OP_IdxInsert; } - sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, - regBase+nOBSat, nBase-nOBSat); + sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); if( iLimit ){ int addr; int r1 = 0; /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit ** register is initialized with value of LIMIT+OFFSET.) After the sorter ** fills up, delete the least entry in the sorter after each insert. ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ - addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); + addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); if( pSort->bOrderedInnerLoop ){ r1 = ++pParse->nMem; sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); VdbeComment((v, "seq")); @@ -116901,12 +115026,11 @@ v = pParse->pVdbe; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N); - sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); sqlite3ReleaseTempReg(pParse, r1); } /* ** This routine generates the code for the inside of the inner loop @@ -116913,11 +115037,11 @@ ** of a SELECT. ** ** If srcTab is negative, then the pEList expressions ** are evaluated in order to get the data for this row. If srcTab is ** zero or more, then data is pulled from srcTab and pEList is used only -** to get the number of columns and the collation sequence for each column. +** to get number columns and the datatype for each column. */ static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ @@ -116928,24 +115052,17 @@ int iContinue, /* Jump here to continue with next row */ int iBreak /* Jump here to break out of the inner loop */ ){ Vdbe *v = pParse->pVdbe; int i; - int hasDistinct; /* True if the DISTINCT keyword is present */ + int hasDistinct; /* True if the DISTINCT keyword is present */ + int regResult; /* Start of memory holding result set */ int eDest = pDest->eDest; /* How to dispose of results */ int iParm = pDest->iSDParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ int nPrefixReg = 0; /* Number of extra registers before regResult */ - /* Usually, regResult is the first cell in an array of memory cells - ** containing the current result row. In this case regOrig is set to the - ** same value. However, if the results are being sent to the sorter, the - ** values for any expressions that are also part of the sort-key are omitted - ** from this array. In this case regOrig is set to zero. */ - int regResult; /* Start of memory holding current results */ - int regOrig; /* Start of memory holding full result (or 0) */ - assert( v ); assert( pEList!=0 ); hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP; if( pSort && pSort->pOrderBy==0 ) pSort = 0; if( pSort==0 && !hasDistinct ){ @@ -116972,11 +115089,11 @@ ** and reported later. But we need to make sure enough memory is allocated ** to avoid other spurious errors in the meantime. */ pParse->nMem += nResultCol; } pDest->nSdst = nResultCol; - regOrig = regResult = pDest->iSdst; + regResult = pDest->iSdst; if( srcTab>=0 ){ for(i=0; ia[i].zName)); } @@ -116988,29 +115105,11 @@ if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ ecelFlags = SQLITE_ECEL_DUP; }else{ ecelFlags = 0; } - if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){ - /* For each expression in pEList that is a copy of an expression in - ** the ORDER BY clause (pSort->pOrderBy), set the associated - ** iOrderByCol value to one more than the index of the ORDER BY - ** expression within the sort-key that pushOntoSorter() will generate. - ** This allows the pEList field to be omitted from the sorted record, - ** saving space and CPU cycles. */ - ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF); - for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){ - int j; - if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){ - pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat; - } - } - regOrig = 0; - assert( eDest==SRT_Set || eDest==SRT_Mem - || eDest==SRT_Coroutine || eDest==SRT_Output ); - } - nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags); + sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags); } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. @@ -117080,11 +115179,11 @@ #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); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } /* Construct a record from the query result, but instead of @@ -117117,11 +115216,11 @@ ** current row to the index and proceed with writing it to the ** output table as well. */ int addr = sqlite3VdbeCurrentAddr(v) + 4; sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1); assert( pSort==0 ); } #endif if( pSort ){ pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); @@ -117146,18 +115245,18 @@ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ pushOntoSorter( - pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); + pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg); }else{ int r1 = sqlite3GetTempReg(pParse); assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol, r1, pDest->zAffSdst, nResultCol); sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); } break; } @@ -117172,16 +115271,15 @@ /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell or array of ** memory cells and break out of the scan loop. */ case SRT_Mem: { + assert( nResultCol==pDest->nSdst ); if( pSort ){ - assert( nResultCol<=pDest->nSdst ); pushOntoSorter( - pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg); + pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg); }else{ - assert( nResultCol==pDest->nSdst ); assert( regResult==iParm ); /* The LIMIT clause will jump out of the loop for us */ } break; } @@ -117190,11 +115288,11 @@ case SRT_Coroutine: /* Send data to a co-routine */ case SRT_Output: { /* Return the results */ testcase( eDest==SRT_Coroutine ); testcase( eDest==SRT_Output ); if( pSort ){ - pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol, + pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol); @@ -117240,11 +115338,11 @@ regResult + pSO->a[i].u.x.iOrderByCol - 1, r2+i); } sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey); sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); if( addrTest ) sqlite3VdbeJumpHere(v, addrTest); sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempRange(pParse, r2, nKey+2); break; } @@ -117475,17 +115573,18 @@ ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; - int iCol; int nKey; int iSortTab; /* Sorter cursor to read from */ int nSortData; /* Trailing values to read from sorter */ int i; int bSeq; /* True if sorter record includes seq. no. */ +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS struct ExprList_item *aOutEx = p->pEList->a; +#endif assert( addrBreak<0 ); if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeGoto(v, addrBreak); @@ -117519,22 +115618,15 @@ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; } - for(i=0, iCol=nKey+bSeq; izAffSdst) ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid, pDest->zAffSdst, nColumn); sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); break; } case SRT_Mem: { /* The LIMIT clause will terminate the loop for us */ break; @@ -118052,11 +116144,11 @@ return 0; } /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ assert( db->lookaside.bDisable ); - pTab->nTabRef = 1; + pTab->nRef = 1; pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect); pTab->iPKey = -1; @@ -118283,11 +116375,10 @@ /* Obtain authorization to do a recursive query */ if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return; /* Process the LIMIT and OFFSET clauses, if they exist */ addrBreak = sqlite3VdbeMakeLabel(v); - p->nSelectRow = 320; /* 4 billion rows */ computeLimitRegisters(pParse, p, addrBreak); pLimit = p->pLimit; pOffset = p->pOffset; regLimit = p->iLimit; regOffset = p->iOffset; @@ -118753,11 +116844,11 @@ iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v); r1 = sqlite3GetTempReg(pParse); - iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1); + iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p->pEList, tab1, 0, 0, &dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); @@ -118920,12 +117011,11 @@ testcase( pIn->nSdst>1 ); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1, pDest->zAffSdst, pIn->nSdst); sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1, - pIn->iSdst, pIn->nSdst); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } /* If this is a scalar select that is part of an expression, then @@ -119380,12 +117470,12 @@ } #endif #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* Forward Declarations */ -static void substExprList(Parse*, ExprList*, int, ExprList*); -static void substSelect(Parse*, Select *, int, ExprList*, int); +static void substExprList(sqlite3*, ExprList*, int, ExprList*); +static void substSelect(sqlite3*, Select *, int, ExprList*, int); /* ** Scan through the expression pExpr. Replace every reference to ** a column in table number iTable with a copy of the iColumn-th ** entry in pEList. (But leave references to the ROWID column @@ -119397,62 +117487,52 @@ ** FORM clause entry is iTable. This routine make the necessary ** changes to pExpr so that it refers directly to the source table ** of the subquery rather the result set of the subquery. */ static Expr *substExpr( - Parse *pParse, /* Report errors here */ + sqlite3 *db, /* Report malloc errors to this connection */ Expr *pExpr, /* Expr in which substitution occurs */ int iTable, /* Table to be substituted */ ExprList *pEList /* Substitute expressions */ ){ - sqlite3 *db = pParse->db; if( pExpr==0 ) return 0; if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; - Expr *pCopy = pEList->a[pExpr->iColumn].pExpr; assert( pEList!=0 && pExpr->iColumnnExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); - if( sqlite3ExprIsVector(pCopy) ){ - sqlite3VectorErrorMsg(pParse, pCopy); - }else{ - pNew = sqlite3ExprDup(db, pCopy, 0); - if( pNew && (pExpr->flags & EP_FromJoin) ){ - pNew->iRightJoinTable = pExpr->iRightJoinTable; - pNew->flags |= EP_FromJoin; - } - sqlite3ExprDelete(db, pExpr); - pExpr = pNew; - } - } - }else{ - pExpr->pLeft = substExpr(pParse, pExpr->pLeft, iTable, pEList); - pExpr->pRight = substExpr(pParse, pExpr->pRight, iTable, pEList); + pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); + sqlite3ExprDelete(db, pExpr); + pExpr = pNew; + } + }else{ + pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); + pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ - substSelect(pParse, pExpr->x.pSelect, iTable, pEList, 1); + substSelect(db, pExpr->x.pSelect, iTable, pEList, 1); }else{ - substExprList(pParse, pExpr->x.pList, iTable, pEList); + substExprList(db, pExpr->x.pList, iTable, pEList); } } return pExpr; } static void substExprList( - Parse *pParse, /* Report errors here */ + sqlite3 *db, /* Report malloc errors here */ ExprList *pList, /* List to scan and in which to make substitutes */ int iTable, /* Table to be substituted */ ExprList *pEList /* Substitute values */ ){ int i; if( pList==0 ) return; for(i=0; inExpr; i++){ - pList->a[i].pExpr = substExpr(pParse, pList->a[i].pExpr, iTable, pEList); + pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList); } } static void substSelect( - Parse *pParse, /* Report errors here */ + sqlite3 *db, /* Report malloc errors here */ Select *p, /* SELECT statement in which to make substitutions */ int iTable, /* Table to be replaced */ ExprList *pEList, /* Substitute values */ int doPrior /* Do substitutes on p->pPrior too */ ){ @@ -119459,21 +117539,21 @@ SrcList *pSrc; struct SrcList_item *pItem; int i; if( !p ) return; do{ - substExprList(pParse, p->pEList, iTable, pEList); - substExprList(pParse, p->pGroupBy, iTable, pEList); - substExprList(pParse, p->pOrderBy, iTable, pEList); - p->pHaving = substExpr(pParse, p->pHaving, iTable, pEList); - p->pWhere = substExpr(pParse, p->pWhere, iTable, pEList); + substExprList(db, p->pEList, iTable, pEList); + substExprList(db, p->pGroupBy, iTable, pEList); + substExprList(db, p->pOrderBy, iTable, pEList); + p->pHaving = substExpr(db, p->pHaving, iTable, pEList); + p->pWhere = substExpr(db, p->pWhere, iTable, pEList); pSrc = p->pSrc; assert( pSrc!=0 ); for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ - substSelect(pParse, pItem->pSelect, iTable, pEList, 1); + substSelect(db, pItem->pSelect, iTable, pEList, 1); if( pItem->fg.isTabFunc ){ - substExprList(pParse, pItem->u1.pFuncArg, iTable, pEList); + substExprList(db, pItem->u1.pFuncArg, iTable, pEList); } } }while( doPrior && (p = p->pPrior)!=0 ); } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ @@ -119866,16 +117946,16 @@ ** ** pSubitem->pTab is always non-NULL by test restrictions and tests above. */ if( ALWAYS(pSubitem->pTab!=0) ){ Table *pTabToDel = pSubitem->pTab; - if( pTabToDel->nTabRef==1 ){ + if( pTabToDel->nRef==1 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); pTabToDel->pNextZombie = pToplevel->pZombieTab; pToplevel->pZombieTab = pTabToDel; }else{ - pTabToDel->nTabRef--; + pTabToDel->nRef--; } pSubitem->pTab = 0; } /* The following loop runs once for each term in a compound-subquery @@ -119994,13 +118074,11 @@ assert( pParent->pGroupBy==0 ); pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); }else{ pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere); } - if( db->mallocFailed==0 ){ - substSelect(pParse, pParent, iParent, pSub->pEList, 0); - } + substSelect(db, pParent, iParent, pSub->pEList, 0); /* The flattened query is distinct if either the inner or the ** outer query is distinct. */ pParent->selFlags |= pSub->selFlags & SF_Distinct; @@ -120070,11 +118148,11 @@ ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( - Parse *pParse, /* Parse context (for malloc() and error reporting) */ + sqlite3 *db, /* The database connection (for malloc()) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ int iCursor /* Cursor number of the subquery */ ){ Expr *pNew; @@ -120091,20 +118169,20 @@ } if( pSubq->pLimit!=0 ){ return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); + nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor); pWhere = pWhere->pLeft; } if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */ if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ nChng++; while( pSubq ){ - pNew = sqlite3ExprDup(pParse->db, pWhere, 0); - pNew = substExpr(pParse, pNew, iCursor, pSubq->pEList); - pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew); + pNew = sqlite3ExprDup(db, pWhere, 0); + pNew = substExpr(db, pNew, iCursor, pSubq->pEList); + pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew); pSubq = pSubq->pPrior; } } return nChng; } @@ -120392,11 +118470,11 @@ if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR; assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; - pTab->nTabRef = 1; + pTab->nRef = 1; pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); @@ -120415,37 +118493,29 @@ && pItem->zName!=0 && 0==sqlite3StrICmp(pItem->zName, pCte->zName) ){ pItem->pTab = pTab; pItem->fg.isRecursive = 1; - pTab->nTabRef++; + pTab->nRef++; pSel->selFlags |= SF_Recursive; } } } /* Only one recursive reference is permitted. */ - if( pTab->nTabRef>2 ){ + if( pTab->nRef>2 ){ sqlite3ErrorMsg( pParse, "multiple references to recursive table: %s", pCte->zName ); return SQLITE_ERROR; } - assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 )); + assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); pCte->zCteErr = "circular reference: %s"; pSavedWith = pParse->pWith; pParse->pWith = pWith; - if( bMayRecursive ){ - Select *pPrior = pSel->pPrior; - assert( pPrior->pWith==0 ); - pPrior->pWith = pSel->pWith; - sqlite3WalkSelect(pWalker, pPrior); - pPrior->pWith = 0; - }else{ - sqlite3WalkSelect(pWalker, pSel); - } + sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); pParse->pWith = pWith; for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); pEList = pLeft->pEList; if( pCte->pCols ){ @@ -120485,16 +118555,14 @@ ** sqlite3SelectExpand() when walking a SELECT tree to resolve table ** names and other FROM clause elements. */ static void selectPopWith(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; - if( pParse->pWith && p->pPrior==0 ){ - With *pWith = findRightmost(p)->pWith; - if( pWith!=0 ){ - assert( pParse->pWith==pWith ); - pParse->pWith = pWith->pOuter; - } + With *pWith = findRightmost(p)->pWith; + if( pWith!=0 ){ + assert( pParse->pWith==pWith ); + pParse->pWith = pWith->pOuter; } } #else #define selectPopWith 0 #endif @@ -120540,12 +118608,12 @@ if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){ return WRC_Prune; } pTabList = p->pSrc; pEList = p->pEList; - if( p->pWith ){ - sqlite3WithPush(pParse, p->pWith, 0); + if( pWalker->xSelectCallback2==selectPopWith ){ + sqlite3WithPush(pParse, findRightmost(p)->pWith, 0); } /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ @@ -120571,11 +118639,11 @@ assert( pSel!=0 ); assert( pFrom->pTab==0 ); if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; - pTab->nTabRef = 1; + pTab->nRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); @@ -120584,17 +118652,17 @@ }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom); if( pTab==0 ) return WRC_Abort; - if( pTab->nTabRef>=0xffff ){ + if( pTab->nRef==0xffff ){ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535", pTab->zName); pFrom->pTab = 0; return WRC_Abort; } - pTab->nTabRef++; + pTab->nRef++; if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ return WRC_Abort; } #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( IsVirtual(pTab) || pTab->pSelect ){ @@ -120740,14 +118808,14 @@ zColname = zName; zToFree = 0; if( longNames || pTabList->nSrc>1 ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); if( zSchemaName ){ pLeft = sqlite3Expr(db, TK_ID, zSchemaName); - pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr); + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0); } if( longNames ){ zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); zToFree = zColname; } @@ -120828,11 +118896,13 @@ if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; - w.xSelectCallback2 = selectPopWith; + if( (pSelect->selFlags & SF_MultiValue)==0 ){ + w.xSelectCallback2 = selectPopWith; + } sqlite3WalkSelect(&w, pSelect); } #ifndef SQLITE_OMIT_SUBQUERY @@ -120978,12 +119048,12 @@ int i; struct AggInfo_func *pF; for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ ExprList *pList = pF->pExpr->x.pList; assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); - sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0, + (void*)pF->pFunc, P4_FUNCDEF); } } /* ** Update the accumulator memory cells for an aggregate based on @@ -121030,12 +119100,12 @@ pColl = pParse->db->pDfltColl; } if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); - sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF); + sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem, + (void*)pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); @@ -121265,11 +119335,11 @@ /* Make copies of constant WHERE-clause terms in the outer query down ** inside the subquery. This can help the subquery to run more efficiently. */ if( (pItem->fg.jointype & JT_OUTER)==0 - && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) + && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor) ){ #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); sqlite3TreeViewSelect(0, p, 0); @@ -121427,13 +119497,11 @@ } /* Set the limiter. */ iEnd = sqlite3VdbeMakeLabel(v); - if( (p->selFlags & SF_FixedLimit)==0 ){ - p->nSelectRow = 320; /* 4 billion rows */ - } + p->nSelectRow = 320; /* 4 billion rows */ computeLimitRegisters(pParse, p, iEnd); if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); sSort.sortFlags |= SORTFLAG_UseSorter; } @@ -121907,11 +119975,11 @@ /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0); if( pWInfo==0 ){ sqlite3ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); @@ -121996,10 +120064,12 @@ ** ** These routines are in a separate files so that they will not be linked ** if they are not used. */ /* #include "sqliteInt.h" */ +/* #include */ +/* #include */ #ifndef SQLITE_OMIT_GET_TABLE /* ** This structure is used to pass data from sqlite3_get_table() through @@ -122488,11 +120558,11 @@ if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zDbSName, MASTER_NAME, zName, + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); @@ -122739,11 +120809,11 @@ */ assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", - db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName ); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); } } @@ -123351,18 +121421,18 @@ VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); assert( inCol ); sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, pCol->affinity, &pValue); if( pValue ){ - sqlite3VdbeAppendP4(v, pValue, P4_MEM); + sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); } - } #ifndef SQLITE_OMIT_FLOATING_POINT - if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ - sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); + if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); + } +#endif } -#endif } /* ** Process an UPDATE statement. ** @@ -123387,11 +121457,11 @@ int nIdx; /* Number of indices that need updating */ int iBaseCur; /* Base cursor number */ int iDataCur; /* Cursor for the canonical data btree */ int iIdxCur; /* Cursor for the first index */ sqlite3 *db; /* The database structure */ - int *aRegIdx = 0; /* First register in array assigned to each index */ + int *aRegIdx = 0; /* One register assigned to each index to be updated */ int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the ** an expression for the i-th column of the table. ** aXRef[i]==-1 if the i-th column is not changed. */ u8 *aToOpen; /* 1 for tables and indices to be opened */ u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */ @@ -123399,15 +121469,14 @@ u8 chngKey; /* Either chngPk or chngRowid */ Expr *pRowidExpr = 0; /* Expression defining the new record number */ AuthContext sContext; /* The authorization context */ NameContext sNC; /* The name-context to resolve expressions in */ int iDb; /* Database containing the table being updated */ - int eOnePass; /* ONEPASS_XXX value from where.c */ + int okOnePass; /* True for one-pass algorithm without the FIFO */ int hasFK; /* True if foreign key processing is required */ int labelBreak; /* Jump here to break out of UPDATE loop */ int labelContinue; /* Jump here to continue next step of UPDATE loop */ - int flags; /* Flags for sqlite3WhereBegin() */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True when updating a view (INSTEAD OF trigger) */ Trigger *pTrigger; /* List of triggers on pTab, if required */ int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ @@ -123414,14 +121483,10 @@ #endif int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ int iEph = 0; /* Ephemeral table holding all primary key values */ int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ - int addrOpen = 0; /* Address of OP_OpenEphemeral */ - int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */ - i16 nPk = 0; /* Number of components of the PRIMARY KEY */ - int bReplace = 0; /* True if REPLACE conflict resolution might happen */ /* Register Allocations */ int regRowCount = 0; /* A count of rows changed */ int regOldRowid = 0; /* The old rowid */ int regNewRowid = 0; /* The new rowid */ @@ -123569,35 +121634,23 @@ */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ reg = ++pParse->nMem; - pParse->nMem += pIdx->nColumn; }else{ reg = 0; for(i=0; inKeyCol; i++){ i16 iIdxCol = pIdx->aiColumn[i]; if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ reg = ++pParse->nMem; - pParse->nMem += pIdx->nColumn; - if( (onError==OE_Replace) - || (onError==OE_Default && pIdx->onError==OE_Replace) - ){ - bReplace = 1; - } break; } } } if( reg==0 ) aToOpen[j+1] = 0; aRegIdx[j] = reg; } - if( bReplace ){ - /* If REPLACE conflict resolution might be invoked, open cursors on all - ** indexes in case they are needed to delete records. */ - memset(aToOpen, 1, nIdx+1); - } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); @@ -123646,134 +121699,114 @@ pWhere, onError); goto update_cleanup; } #endif - /* Initialize the count of updated rows */ - if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ - regRowCount = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); - } - + /* Begin the database scan + */ if( HasRowid(pTab) ){ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); + pWInfo = sqlite3WhereBegin( + pParse, pTabList, pWhere, 0, 0, + WHERE_ONEPASS_DESIRED | WHERE_SEEK_TABLE, iIdxCur + ); + if( pWInfo==0 ) goto update_cleanup; + okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); + + /* Remember the rowid of every item to be updated. + */ + sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); + if( !okOnePass ){ + sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); + } + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); }else{ + int iPk; /* First of nPk memory cells holding PRIMARY KEY value */ + i16 nPk; /* Number of components of the PRIMARY KEY */ + int addrOpen; /* Address of the OpenEphemeral instruction */ + assert( pPk!=0 ); nPk = pPk->nKeyCol; iPk = pParse->nMem+1; pParse->nMem += nPk; regKey = ++pParse->nMem; iEph = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); sqlite3VdbeSetP4KeyInfo(pParse, pPk); - } - - /* Begin the database scan. - ** - ** Do not consider a single-pass strategy for a multi-row update if - ** there are any triggers or foreign keys to process, or rows may - ** be deleted as a result of REPLACE conflict handling. Any of these - ** things might disturb a cursor being used to scan through the table - ** or index, causing a single-pass approach to malfunction. */ - flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE; - if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ - flags |= WHERE_ONEPASS_MULTIROW; - } - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur); - if( pWInfo==0 ) goto update_cleanup; - - /* A one-pass strategy that might update more than one row may not - ** be used if any column of the index used for the scan is being - ** updated. Otherwise, if there is an index on "b", statements like - ** the following could create an infinite loop: - ** - ** UPDATE t1 SET b=b+1 WHERE b>? - ** - ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI - ** strategy that uses an index for which one or more columns are being - ** updated. */ - eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); - if( eOnePass==ONEPASS_MULTI ){ - int iCur = aiCurOnePass[1]; - if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ - eOnePass = ONEPASS_OFF; - } - assert( iCur!=iDataCur || !HasRowid(pTab) ); - } - - if( HasRowid(pTab) ){ - /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF - ** mode, write the rowid into the FIFO. In either of the one-pass modes, - ** leave it in register regOldRowid. */ - sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); - if( eOnePass==ONEPASS_OFF ){ - sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); - } - }else{ - /* Read the PK of the current row into an array of registers. In - ** ONEPASS_OFF mode, serialize the array into a record and store it in - ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change - ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table - ** is not required) and leave the PK fields in the array of registers. */ + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, + WHERE_ONEPASS_DESIRED, iIdxCur); + if( pWInfo==0 ) goto update_cleanup; + okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); for(i=0; iaiColumn[i]>=0 ); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], + iPk+i); } - if( eOnePass ){ + if( okOnePass ){ sqlite3VdbeChangeToNoop(v, addrOpen); nKey = nPk; regKey = iPk; }else{ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, sqlite3IndexAffinityStr(db, pPk), nPk); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); } - } - - if( eOnePass!=ONEPASS_MULTI ){ sqlite3WhereEnd(pWInfo); } + + /* Initialize the count of updated rows + */ + if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } labelBreak = sqlite3VdbeMakeLabel(v); if( !isView ){ - int addrOnce = 0; - - /* Open every index that needs updating. */ - if( eOnePass!=ONEPASS_OFF ){ + /* + ** Open every index that needs updating. Note that if any + ** index could potentially invoke a REPLACE conflict resolution + ** action, then we need to open all indices because we might need + ** to be deleting some records. + */ + if( onError==OE_Replace ){ + memset(aToOpen, 1, nIdx+1); + }else{ + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->onError==OE_Replace ){ + memset(aToOpen, 1, nIdx+1); + break; + } + } + } + if( okOnePass ){ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; } - - if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ - addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); - } sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, 0, 0); - if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); } /* Top of the update loop */ - if( eOnePass!=ONEPASS_OFF ){ - if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ + if( okOnePass ){ + if( aToOpen[iDataCur-iBaseCur] && !isView ){ assert( pPk ); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); VdbeCoverageNeverTaken(v); } - if( eOnePass==ONEPASS_SINGLE ){ - labelContinue = labelBreak; - }else{ - labelContinue = sqlite3VdbeMakeLabel(v); - } + labelContinue = labelBreak; sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); VdbeCoverageIf(v, pPk==0); VdbeCoverageIf(v, pPk!=0); }else if( pPk ){ labelContinue = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); - addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); + addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); VdbeCoverage(v); }else{ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, regOldRowid); @@ -123887,10 +121920,11 @@ } } if( !isView ){ int addr1 = 0; /* Address of jump instruction */ + int bReplace = 0; /* True if REPLACE conflict resolution might happen */ /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, @@ -123922,22 +121956,18 @@ ** is the column index supplied by the user. */ assert( regNew==regNewRowid+1 ); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, - OPFLAG_ISUPDATE | ((hasFK || chngKey) ? 0 : OPFLAG_ISNOOP), + OPFLAG_ISUPDATE | ((hasFK || chngKey || pPk!=0) ? 0 : OPFLAG_ISNOOP), regNewRowid ); - if( eOnePass==ONEPASS_MULTI ){ - assert( hasFK==0 && chngKey==0 ); - sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); - } if( !pParse->nested ){ - sqlite3VdbeAppendP4(v, pTab, P4_TABLE); + sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE); } #else - if( hasFK || chngKey ){ + if( hasFK || chngKey || pPk!=0 ){ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } #endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); @@ -123946,15 +121976,12 @@ if( hasFK ){ sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); } /* Insert the new index entries and the new record. */ - sqlite3CompleteInsertion( - pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, - OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), - 0, 0 - ); + sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, + regNewRowid, aRegIdx, 1, 0, 0); /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to ** handle rows (possibly in other tables) that refer via a foreign key ** to the row just updated. */ if( hasFK ){ @@ -123972,23 +121999,29 @@ TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); /* Repeat the above with the next record to be updated, until ** all record selected by the WHERE clause have been updated. */ - if( eOnePass==ONEPASS_SINGLE ){ + if( okOnePass ){ /* Nothing to do at end-of-loop for a single-pass */ - }else if( eOnePass==ONEPASS_MULTI ){ - sqlite3VdbeResolveLabel(v, labelContinue); - sqlite3WhereEnd(pWInfo); }else if( pPk ){ sqlite3VdbeResolveLabel(v, labelContinue); sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); }else{ sqlite3VdbeGoto(v, labelContinue); } sqlite3VdbeResolveLabel(v, labelBreak); + /* Close all tables */ + for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ + assert( aRegIdx ); + if( aToOpen[i+1] ){ + sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0); + } + } + if( iDataCurnested==0 && pParse->pTriggerTab==0 ){ @@ -124250,29 +122283,12 @@ ** transient would cause the database file to appear to be deleted ** following reboot. */ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){ Vdbe *v = sqlite3GetVdbe(pParse); - int iDb = 0; - if( v==0 ) return; - if( pNm ){ -#ifndef SQLITE_BUG_COMPATIBLE_20160819 - /* Default behavior: Report an error if the argument to VACUUM is - ** not recognized */ - iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm); - if( iDb<0 ) return; -#else - /* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments - ** to VACUUM are silently ignored. This is a back-out of a bug fix that - ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270). - ** The buggy behavior is required for binary compatibility with some - ** legacy applications. */ - iDb = sqlite3FindDb(pParse->db, pNm); - if( iDb<0 ) iDb = 0; -#endif - } - if( iDb!=1 ){ + int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0; + if( v && (iDb>=2 || iDb==0) ){ sqlite3VdbeAddOp1(v, OP_Vacuum, iDb); sqlite3VdbeUsesBtree(v, iDb); } return; } @@ -124551,45 +122567,10 @@ Table *pTab; /* The Table object to which the virtual table belongs */ VtabCtx *pPrior; /* Parent context (if any) */ int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; -/* -** Construct and install a Module object for a virtual table. When this -** routine is called, it is guaranteed that all appropriate locks are held -** and the module is not already part of the connection. -*/ -SQLITE_PRIVATE Module *sqlite3VtabCreateModule( - sqlite3 *db, /* Database in which module is registered */ - const char *zName, /* Name assigned to this module */ - const sqlite3_module *pModule, /* The definition of the module */ - void *pAux, /* Context pointer for xCreate/xConnect */ - void (*xDestroy)(void *) /* Module destructor function */ -){ - Module *pMod; - int nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); - if( pMod ){ - Module *pDel; - char *zCopy = (char *)(&pMod[1]); - memcpy(zCopy, zName, nName+1); - pMod->zName = zCopy; - pMod->pModule = pModule; - pMod->pAux = pAux; - pMod->xDestroy = xDestroy; - pMod->pEpoTab = 0; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); - assert( pDel==0 || pDel==pMod ); - if( pDel ){ - sqlite3OomFault(db); - sqlite3DbFree(db, pDel); - pMod = 0; - } - } - return pMod; -} - /* ** The actual function that does the work of creating a new module. ** This function implements the sqlite3_create_module() and ** sqlite3_create_module_v2() interfaces. */ @@ -124599,19 +122580,39 @@ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ int rc = SQLITE_OK; + int nName; sqlite3_mutex_enter(db->mutex); + nName = sqlite3Strlen30(zName); if( sqlite3HashFind(&db->aModule, zName) ){ rc = SQLITE_MISUSE_BKPT; }else{ - (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); + Module *pMod; + pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); + if( pMod ){ + Module *pDel; + char *zCopy = (char *)(&pMod[1]); + memcpy(zCopy, zName, nName+1); + pMod->zName = zCopy; + pMod->pModule = pModule; + pMod->pAux = pAux; + pMod->xDestroy = xDestroy; + pMod->pEpoTab = 0; + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); + assert( pDel==0 || pDel==pMod ); + if( pDel ){ + sqlite3OomFault(db); + sqlite3DbFree(db, pDel); + } + } } rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); + sqlite3_mutex_leave(db->mutex); return rc; } @@ -124862,11 +122863,12 @@ db = pParse->db; iDb = sqlite3SchemaToIndex(db, pTable->pSchema); assert( iDb>=0 ); - assert( pTable->nModuleArg==0 ); + pTable->tabFlags |= TF_Virtual; + pTable->nModuleArg = 0; addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); addModuleArgument(db, pTable, 0); addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) || (pParse->sNameToken.z==pName1->z && pName2->z==0) @@ -124945,11 +122947,11 @@ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3NestedParse(pParse, "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zDbSName, MASTER_NAME, + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTab->zName, pTab->zName, zStmt, pParse->regRowid ); @@ -125150,11 +123152,11 @@ const char *zMod; Module *pMod; int rc; assert( pTab ); - if( !IsVirtual(pTab) || sqlite3GetVTable(db, pTab) ){ + if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ return SQLITE_OK; } /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; @@ -125220,11 +123222,11 @@ Table *pTab; Module *pMod; const char *zMod; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); - assert( pTab && IsVirtual(pTab) && !pTab->pVTable ); + assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod); @@ -125274,11 +123276,11 @@ sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } pTab = pCtx->pTab; - assert( IsVirtual(pTab) ); + assert( (pTab->tabFlags & TF_Virtual)!=0 ); pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); if( pParse==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ @@ -125288,11 +123290,11 @@ if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr) && pParse->pNewTable && !db->mallocFailed && !pParse->pNewTable->pSelect - && !IsVirtual(pParse->pNewTable) + && (pParse->pNewTable->tabFlags & TF_Virtual)==0 ){ if( !pTab->aCol ){ Table *pNew = pParse->pNewTable; Index *pIdx; pTab->aCol = pNew->aCol; @@ -125577,11 +123579,11 @@ /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; pTab = pExpr->pTab; if( NEVER(pTab==0) ) return pDef; - if( !IsVirtual(pTab) ) return pDef; + if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction==0 ) return pDef; @@ -125670,13 +123672,14 @@ if( pTab->zName==0 ){ sqlite3DbFree(db, pTab); return 0; } pMod->pEpoTab = pTab; - pTab->nTabRef = 1; + pTab->nRef = 1; pTab->pSchema = db->aDb[0].pSchema; - assert( pTab->nModuleArg==0 ); + pTab->tabFlags |= TF_Virtual; + pTab->nModuleArg = 0; pTab->iPKey = -1; addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); addModuleArgument(db, pTab, 0); addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); @@ -125743,11 +123746,11 @@ case SQLITE_VTAB_CONSTRAINT_SUPPORT: { VtabCtx *p = db->pVtabCtx; if( !p ){ rc = SQLITE_MISUSE_BKPT; }else{ - assert( p->pTab==0 || IsVirtual(p->pTab) ); + assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 ); p->pVTable->bConstraint = (u8)va_arg(ap, int); } break; } default: @@ -126182,17 +124185,12 @@ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 UnpackedRecord *pRec; /* Probe for stat4 (if required) */ int nRecValid; /* Number of valid fields currently in pRec */ #endif - unsigned int bldFlags; /* SQLITE_BLDF_* flags */ }; -/* Allowed values for WhereLoopBuider.bldFlags */ -#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ -#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ - /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed @@ -126203,11 +124201,11 @@ */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ - ExprList *pResultSet; /* Result set of the query */ + ExprList *pDistinctSet; /* DISTINCT over all these values */ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ @@ -126771,11 +124769,10 @@ if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0); }else{ Select *pSelect = pX->x.pSelect; sqlite3 *db = pParse->db; - u16 savedDbOptFlags = db->dbOptFlags; ExprList *pOrigRhs = pSelect->pEList; ExprList *pOrigLhs = pX->pLeft->x.pList; ExprList *pRhs = 0; /* New Select.pEList for RHS */ ExprList *pLhs = 0; /* New pX->pLeft vector */ @@ -126815,13 +124812,11 @@ pLeft->x.pList = pLhs; aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * nEq); testcase( aiMap==0 ); } pSelect->pEList = pRhs; - db->dbOptFlags |= SQLITE_QueryFlattener; eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap); - db->dbOptFlags = savedDbOptFlags; testcase( aiMap!=0 && aiMap[0]!=0 ); pSelect->pEList = pOrigRhs; pLeft->x.pList = pOrigLhs; pX->pLeft = pLeft; } @@ -127387,11 +125382,10 @@ Parse *pParse; /* Parsing context */ sqlite3 *db; /* Database connection */ Vdbe *v; /* The prepared stmt under constructions */ struct SrcList_item *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ - int addrHalt; /* addrBrk for the outermost loop */ int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ pParse = pWInfo->pParse; @@ -127429,15 +125423,10 @@ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } - /* Compute a safe address to jump to if we discover that the table for - ** this loop is empty and can never contribute content. */ - for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){} - addrHalt = pWInfo->a[j].addrBrk; - /* Special case of a FROM clause subquery implemented as a co-routine */ if( pTabItem->fg.viaCoroutine ){ int regYield = pTabItem->regReturn; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub); pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk); @@ -127473,11 +125462,11 @@ } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, - pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC); + pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); VdbeCoverage(v); pLoop->u.vtab.needFree = 0; pLevel->p1 = iCur; pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); @@ -127506,11 +125495,11 @@ sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); } /* Generate code that will continue to the next row if ** the IN constraint is not satisfied */ - pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); + pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0, 0); assert( pCompare!=0 || db->mallocFailed ); if( pCompare ){ pCompare->pLeft = pTerm->pExpr->pLeft; pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); if( pRight ){ @@ -127618,11 +125607,11 @@ VdbeCoverageIf(v, pX->op==TK_LT); VdbeCoverageIf(v, pX->op==TK_GE); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); }else{ - sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt); + sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); } if( pEnd ){ Expr *pX; @@ -127922,14 +125911,11 @@ /* Seek the table cursor, if required */ if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ - if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || ( - (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE) - && (pWInfo->eOnePass==ONEPASS_SINGLE) - )){ + if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)!=0 ){ iRowidReg = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg); sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg); VdbeCoverage(v); @@ -128108,11 +126094,11 @@ testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ - pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr); + pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr, 0); } } /* Run a separate WHERE clause for each term of the OR clause. After ** eliminating duplicates from other WHERE clauses, the action for each @@ -128181,12 +126167,11 @@ jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk); VdbeCoverage(v); } if( iSet>=0 ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid, - r, nPk); + sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0); if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); } /* Release the array of temp registers */ sqlite3ReleaseTempRange(pParse, r, nPk); @@ -128264,11 +126249,11 @@ pLevel->op = OP_Noop; }else{ codeCursorHint(pTabItem, pWInfo, pLevel, 0); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; - pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt); + pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } } @@ -128589,10 +126574,19 @@ #ifdef SQLITE_EBCDIC if( *pnoCase ) return 0; #endif pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT + || IsVirtual(pLeft->pTab) /* Value might be numeric */ + ){ + /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must + ** be the name of an indexed column with TEXT affinity. */ + return 0; + } + assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr); op = pRight->op; if( op==TK_VARIABLE ){ Vdbe *pReprepare = pParse->pReprepare; @@ -128605,27 +126599,10 @@ assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); }else if( op==TK_STRING ){ z = pRight->u.zToken; } if( z ){ - - /* If the RHS begins with a digit or a minus sign, then the LHS must - ** be an ordinary column (not a virtual table column) with TEXT affinity. - ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false - ** even though "lhs LIKE rhs" is true. But if the RHS does not start - ** with a digit or '-', then "lhs LIKE rhs" will always be false if - ** the LHS is numeric and so the optimization still works. - */ - if( sqlite3Isdigit(z[0]) || z[0]=='-' ){ - if( pLeft->op!=TK_COLUMN - || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ - ){ - sqlite3ValueFree(pVal); - return 0; - } - } cnt = 0; while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ cnt++; } if( cnt!=0 && 255!=(u8)z[cnt-1] ){ @@ -129118,11 +127095,11 @@ pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); pDup = sqlite3ExprDup(db, pLeft, 0); - pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0); + pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0, 0); if( pNew ){ int idxNew; transferJoinMarkings(pNew, pExpr); assert( !ExprHasProperty(pNew, EP_xIsSelect) ); pNew->x.pList = pList; @@ -129250,11 +127227,11 @@ iCur = pFrom->a[i].iCursor; for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->aColExpr==0 ) continue; for(i=0; inKeyCol; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; - if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ + if( sqlite3ExprCompare(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ *piCur = iCur; *piColumn = XN_EXPR; return 1; } } @@ -129297,11 +127274,10 @@ int noCase = 0; /* uppercase equivalent to lowercase */ int op; /* Top-level operator. pExpr->op */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection */ unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */ - int nLeft; /* Number of elements on left side vector */ if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; @@ -129327,14 +127303,10 @@ if( ExprHasProperty(pExpr, EP_FromJoin) ){ Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); prereqAll |= x; extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ - if( (prereqAll>>1)>=x ){ - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); - return; - } } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; @@ -129421,11 +127393,11 @@ for(i=0; i<2; i++){ Expr *pNewExpr; int idxNew; pNewExpr = sqlite3PExpr(pParse, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0), - sqlite3ExprDup(db, pList->a[i].pExpr, 0)); + sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0); transferJoinMarkings(pNewExpr, pExpr); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); exprAnalyze(pSrc, pWC, idxNew); pTerm = &pWC->a[idxTerm]; @@ -129506,19 +127478,19 @@ } zCollSeqName = noCase ? "NOCASE" : "BINARY"; pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), - pStr1); + pStr1, 0); transferJoinMarkings(pNewExpr1, pExpr); idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), - pStr2); + pStr2, 0); transferJoinMarkings(pNewExpr2, pExpr); idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; @@ -129547,11 +127519,11 @@ prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft); if( (prereqExpr & prereqColumn)==0 ){ Expr *pNewExpr; pNewExpr = sqlite3PExpr(pParse, TK_MATCH, - 0, sqlite3ExprDup(db, pRight, 0)); + 0, sqlite3ExprDup(db, pRight, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); pNewTerm = &pWC->a[idxNew]; pNewTerm->prereqRight = prereqExpr; pNewTerm->leftCursor = pLeft->iTable; @@ -129573,23 +127545,24 @@ ** ** This is only required if at least one side of the comparison operation ** is not a sub-select. */ if( pWC->op==TK_AND && (pExpr->op==TK_EQ || pExpr->op==TK_IS) - && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 - && sqlite3ExprVectorSize(pExpr->pRight)==nLeft + && sqlite3ExprIsVector(pExpr->pLeft) && ( (pExpr->pLeft->flags & EP_xIsSelect)==0 - || (pExpr->pRight->flags & EP_xIsSelect)==0) - ){ + || (pExpr->pRight->flags & EP_xIsSelect)==0 + )){ + int nLeft = sqlite3ExprVectorSize(pExpr->pLeft); int i; + assert( nLeft==sqlite3ExprVectorSize(pExpr->pRight) ); for(i=0; ipLeft, i); Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i); - pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); + pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0); transferJoinMarkings(pNew, pExpr); idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); exprAnalyze(pSrc, pWC, idxNew); } pTerm = &pWC->a[idxTerm]; @@ -129637,11 +127610,11 @@ int idxNew; WhereTerm *pNewTerm; pNewExpr = sqlite3PExpr(pParse, TK_GT, sqlite3ExprDup(db, pLeft, 0), - sqlite3ExprAlloc(db, TK_NULL, 0, 0)); + sqlite3ExprAlloc(db, TK_NULL, 0, 0), 0); idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL); if( idxNew ){ pNewTerm = &pWC->a[idxNew]; @@ -129658,12 +127631,10 @@ #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ - testcase( pTerm!=&pWC->a[idxTerm] ); - pTerm = &pWC->a[idxTerm]; pTerm->prereqRight |= extraRight; } /*************************************************************************** ** Routines with file scope above. Interface to the rest of the where.c @@ -129823,11 +127794,11 @@ if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; pColRef->pTab = pTab; pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); + sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } /************** End of whereexpr.c *******************************************/ @@ -130030,23 +128001,20 @@ Expr *pX; /* An expression being tested */ WhereClause *pWC; /* Shorthand for pScan->pWC */ WhereTerm *pTerm; /* The term being tested */ int k = pScan->k; /* Where to start scanning */ - assert( pScan->iEquiv<=pScan->nEquiv ); - pWC = pScan->pWC; - while(1){ + while( pScan->iEquiv<=pScan->nEquiv ){ + iCur = pScan->aiCur[pScan->iEquiv-1]; iColumn = pScan->aiColumn[pScan->iEquiv-1]; - iCur = pScan->aiCur[pScan->iEquiv-1]; - assert( pWC!=0 ); - do{ + if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0; + while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+k; knTerm; k++, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn && (iColumn!=XN_EXPR - || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, - pScan->pIdxExpr,iCur)==0) + || sqlite3ExprCompare(pTerm->pExpr->pLeft,pScan->pIdxExpr,iCur)==0) && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaiCur) && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN @@ -130087,21 +128055,19 @@ && pX->iColumn==pScan->aiColumn[0] ){ testcase( pTerm->eOperator & WO_IS ); continue; } - pScan->pWC = pWC; pScan->k = k+1; return pTerm; } } } - pWC = pWC->pOuter; + pScan->pWC = pScan->pWC->pOuter; k = 0; - }while( pWC!=0 ); - if( pScan->iEquiv>=pScan->nEquiv ) break; - pWC = pScan->pOrigWC; + } + pScan->pWC = pScan->pOrigWC; k = 0; pScan->iEquiv++; } return 0; } @@ -130131,29 +128097,28 @@ int iCur, /* Cursor to scan for */ int iColumn, /* Column to scan for */ u32 opMask, /* Operator(s) to scan for */ Index *pIdx /* Must be compatible with this index */ ){ + int j = 0; + + /* memset(pScan, 0, sizeof(*pScan)); */ pScan->pOrigWC = pWC; pScan->pWC = pWC; pScan->pIdxExpr = 0; - pScan->idxaff = 0; - pScan->zCollName = 0; if( pIdx ){ - int j = iColumn; + j = iColumn; iColumn = pIdx->aiColumn[j]; - if( iColumn==XN_EXPR ){ - pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - pScan->zCollName = pIdx->azColl[j]; - }else if( iColumn==pIdx->pTable->iPKey ){ - iColumn = XN_ROWID; - }else if( iColumn>=0 ){ - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; - pScan->zCollName = pIdx->azColl[j]; - } - }else if( iColumn==XN_EXPR ){ - return 0; + if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID; + } + if( pIdx && iColumn>=0 ){ + pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; + pScan->zCollName = pIdx->azColl[j]; + }else{ + pScan->idxaff = 0; + pScan->zCollName = 0; } pScan->opMask = opMask; pScan->k = 0; pScan->aiCur[0] = iCur; pScan->aiColumn[0] = iColumn; @@ -130349,20 +128314,18 @@ ** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero, ** then each OP_Rowid is transformed into an instruction to increment the ** value stored in its output register. */ static void translateColumnToCopy( - Parse *pParse, /* Parsing context */ + Vdbe *v, /* The VDBE containing code to translate */ int iStart, /* Translate from this opcode to the end */ int iTabCur, /* OP_Column/OP_Rowid references to this table */ int iRegister, /* The first column is in this register */ int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */ ){ - Vdbe *v = pParse->pVdbe; VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart); int iEnd = sqlite3VdbeCurrentAddr(v); - if( pParse->db->mallocFailed ) return; for(; iStartp1!=iTabCur ) continue; if( pOp->opcode==OP_Column ){ pOp->opcode = OP_Copy; pOp->p1 = pOp->p2 + iRegister; @@ -130636,13 +128599,11 @@ sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); if( pTabItem->fg.viaCoroutine ){ sqlite3VdbeChangeP2(v, addrCounter, regBase+n); - testcase( pParse->db->mallocFailed ); - translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, - pTabItem->regResult, 1); + translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult, 1); sqlite3VdbeGoto(v, addrTop); pTabItem->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); } @@ -132223,15 +130184,10 @@ testcase( eOp & WO_IS ); testcase( eOp & WO_ISNULL ); continue; } - if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ - pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; - }else{ - pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; - } pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->u.btree.nBtm = saved_nBtm; pNew->u.btree.nTop = saved_nTop; pNew->nLTerm = saved_nLTerm; @@ -132775,19 +130731,11 @@ pNew->nOut = rSize; if( rc ) break; } } - pBuilder->bldFlags = 0; rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); - if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){ - /* If a non-unique index is used, or if a prefix of the key for - ** unique index is used (making the index functionally non-unique) - ** then the sqlite_stat1 data becomes important for scoring the - ** plan */ - pTab->tabFlags |= TF_StatsUsed; - } #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 sqlite3Stat4ProbeFree(pBuilder->pRec); pBuilder->nRecValid = 0; pBuilder->pRec = 0; #endif @@ -133963,13 +131911,13 @@ && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 && pWInfo->eDistinct==WHERE_DISTINCT_NOOP && nRowEst ){ Bitmask notUsed; - int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, + int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom, WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); - if( rc==pWInfo->pResultSet->nExpr ){ + if( rc==pWInfo->pDistinctSet->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } } if( pWInfo->pOrderBy ){ if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ @@ -134202,11 +132150,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ - ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ + ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */ u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number ** If WHERE_USE_LIMIT, then the limit amount */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ @@ -134278,11 +132226,11 @@ goto whereBeginError; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->pOrderBy = pOrderBy; - pWInfo->pResultSet = pResultSet; + pWInfo->pDistinctSet = pDistinctSet; pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1; pWInfo->nLevel = nTabList; pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; @@ -134356,17 +132304,17 @@ /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( db->mallocFailed ) goto whereBeginError; if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ + if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; }else if( pOrderBy==0 ){ /* Try to ORDER BY the result set to make distinct processing easier */ pWInfo->wctrlFlags |= WHERE_DISTINCTBY; - pWInfo->pOrderBy = pResultSet; + pWInfo->pOrderBy = pDistinctSet; } } /* Construct the WhereLoop objects */ #if defined(WHERETRACE_ENABLED) @@ -134438,14 +132386,14 @@ } } #endif /* Attempt to omit tables from the join that do not effect the result */ if( pWInfo->nLevel>=2 - && pResultSet!=0 + && pDistinctSet!=0 && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); + Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet); if( sWLB.pOrderBy ){ tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); } while( pWInfo->nLevel>=2 ){ WhereTerm *pTerm, *pEnd; @@ -134756,16 +132704,36 @@ /* For a co-routine, change all OP_Column references to the table of ** the co-routine into OP_Copy of result contained in a register. ** OP_Rowid becomes OP_Null. */ - if( pTabItem->fg.viaCoroutine ){ - testcase( pParse->db->mallocFailed ); - translateColumnToCopy(pParse, pLevel->addrBody, pLevel->iTabCur, + if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){ + translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur, pTabItem->regResult, 0); continue; } + + /* Close all of the cursors that were opened by sqlite3WhereBegin. + ** Except, do not close cursors that will be reused by the OR optimization + ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors + ** created for the ONEPASS optimization. + */ + if( (pTab->tabFlags & TF_Ephemeral)==0 + && pTab->pSelect==0 + && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + ){ + int ws = pLoop->wsFlags; + if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ + sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); + } + if( (ws & WHERE_INDEXED)!=0 + && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 + && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1] + ){ + sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); + } + } /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases ** this optimization prevents the table from ever being read, which can ** yield a significant performance boost. @@ -134801,12 +132769,11 @@ x = sqlite3ColumnOfIndex(pIdx, x); if( x>=0 ){ pOp->p2 = x; pOp->p1 = pLevel->iIdxCur; } - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 - || pWInfo->eOnePass ); + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; } } @@ -134866,23 +132833,10 @@ ** Indicate that sqlite3ParserFree() will never be called with a null ** pointer. */ #define YYPARSEFREENEVERNULL 1 -/* -** In the amalgamation, the parse.c file generated by lemon and the -** tokenize.c file are concatenated. In that case, sqlite3RunParser() -** has access to the the size of the yyParser object and so the parser -** engine can be allocated from stack. In that case, only the -** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked -** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be -** omitted. -*/ -#ifdef SQLITE_AMALGAMATION -# define sqlite3Parser_ENGINEALWAYSONSTACK 1 -#endif - /* ** Alternative datatype for the argument to the malloc() routine passed ** into sqlite3ParserAlloc(). The default is size_t. */ #define YYMALLOCARGTYPE u64 @@ -134982,20 +132936,20 @@ Parse *pParse, /* The parsing context. Errors accumulate here */ int op, /* The binary operation */ ExprSpan *pLeft, /* The left operand, and output */ ExprSpan *pRight /* The right operand */ ){ - pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr); + pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); pLeft->zEnd = pRight->zEnd; } /* If doNot is true, then add a TK_NOT Expr-node wrapper around the ** outside of *ppExpr. */ static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ if( doNot ){ - pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0); + pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0, 0); } } /* Construct an expression node for a unary postfix operator */ @@ -135003,11 +132957,11 @@ Parse *pParse, /* Parsing context to record errors */ int op, /* The operator */ ExprSpan *pOperand, /* The operand, and output */ Token *pPostOp /* The operand token for setting the span */ ){ - pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); + pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); pOperand->zEnd = &pPostOp->z[pPostOp->n]; } /* A routine to convert a binary TK_IS or TK_ISNOT expression into a ** unary TK_ISNULL or TK_NOTNULL expression. */ @@ -135028,11 +132982,11 @@ int op, /* The operator */ ExprSpan *pOperand, /* The operand */ Token *pPreOp /* The operand token for setting the span */ ){ pOut->zStart = pPreOp->z; - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); + pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0); pOut->zEnd = pOperand->zEnd; } /* Add a single new term to an ExprList that is used to store a ** list of identifiers. Report an error if the ID list contains @@ -135225,166 +133179,166 @@ ** *********** Begin parsing tables **********************************************/ #define YY_ACTTAB_COUNT (1567) static const YYACTIONTYPE yy_action[] = { /* 0 */ 325, 832, 351, 825, 5, 203, 203, 819, 99, 100, - /* 10 */ 90, 978, 978, 853, 856, 845, 845, 97, 97, 98, + /* 10 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, /* 20 */ 98, 98, 98, 301, 96, 96, 96, 96, 95, 95, - /* 30 */ 94, 94, 94, 93, 351, 325, 976, 976, 824, 824, - /* 40 */ 826, 946, 354, 99, 100, 90, 978, 978, 853, 856, - /* 50 */ 845, 845, 97, 97, 98, 98, 98, 98, 338, 96, + /* 30 */ 94, 94, 94, 93, 351, 325, 977, 977, 824, 824, + /* 40 */ 826, 947, 354, 99, 100, 90, 842, 842, 854, 857, + /* 50 */ 846, 846, 97, 97, 98, 98, 98, 98, 338, 96, /* 60 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, - /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 976, 976, + /* 70 */ 95, 95, 94, 94, 94, 93, 351, 791, 977, 977, /* 80 */ 325, 94, 94, 94, 93, 351, 792, 75, 99, 100, - /* 90 */ 90, 978, 978, 853, 856, 845, 845, 97, 97, 98, + /* 90 */ 90, 842, 842, 854, 857, 846, 846, 97, 97, 98, /* 100 */ 98, 98, 98, 450, 96, 96, 96, 96, 95, 95, /* 110 */ 94, 94, 94, 93, 351, 1333, 155, 155, 2, 325, /* 120 */ 275, 146, 132, 52, 52, 93, 351, 99, 100, 90, - /* 130 */ 978, 978, 853, 856, 845, 845, 97, 97, 98, 98, + /* 130 */ 842, 842, 854, 857, 846, 846, 97, 97, 98, 98, /* 140 */ 98, 98, 101, 96, 96, 96, 96, 95, 95, 94, - /* 150 */ 94, 94, 93, 351, 957, 957, 325, 268, 428, 413, - /* 160 */ 411, 61, 752, 752, 99, 100, 90, 978, 978, 853, - /* 170 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 60, + /* 150 */ 94, 94, 93, 351, 958, 958, 325, 268, 428, 413, + /* 160 */ 411, 61, 752, 752, 99, 100, 90, 842, 842, 854, + /* 170 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 60, /* 180 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 190 */ 351, 325, 270, 329, 273, 277, 958, 959, 250, 99, - /* 200 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, + /* 190 */ 351, 325, 270, 329, 273, 277, 959, 960, 250, 99, + /* 200 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, /* 210 */ 98, 98, 98, 98, 301, 96, 96, 96, 96, 95, - /* 220 */ 95, 94, 94, 94, 93, 351, 325, 937, 1326, 698, - /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 978, 978, 853, - /* 240 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 347, + /* 220 */ 95, 94, 94, 94, 93, 351, 325, 938, 1326, 698, + /* 230 */ 706, 1326, 242, 412, 99, 100, 90, 842, 842, 854, + /* 240 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 347, /* 250 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 260 */ 351, 325, 937, 1327, 384, 699, 1327, 381, 379, 99, - /* 270 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, + /* 260 */ 351, 325, 938, 1327, 384, 699, 1327, 381, 379, 99, + /* 270 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, /* 280 */ 98, 98, 98, 98, 701, 96, 96, 96, 96, 95, /* 290 */ 95, 94, 94, 94, 93, 351, 325, 92, 89, 178, - /* 300 */ 833, 935, 373, 700, 99, 100, 90, 978, 978, 853, - /* 310 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 375, + /* 300 */ 833, 936, 373, 700, 99, 100, 90, 842, 842, 854, + /* 310 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 375, /* 320 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 330 */ 351, 325, 1275, 946, 354, 818, 935, 739, 739, 99, - /* 340 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, + /* 330 */ 351, 325, 1276, 947, 354, 818, 936, 739, 739, 99, + /* 340 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, /* 350 */ 98, 98, 98, 98, 230, 96, 96, 96, 96, 95, - /* 360 */ 95, 94, 94, 94, 93, 351, 325, 968, 227, 92, - /* 370 */ 89, 178, 373, 300, 99, 100, 90, 978, 978, 853, - /* 380 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 920, + /* 360 */ 95, 94, 94, 94, 93, 351, 325, 969, 227, 92, + /* 370 */ 89, 178, 373, 300, 99, 100, 90, 842, 842, 854, + /* 380 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 921, /* 390 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, /* 400 */ 351, 325, 449, 447, 447, 447, 147, 737, 737, 99, - /* 410 */ 100, 90, 978, 978, 853, 856, 845, 845, 97, 97, + /* 410 */ 100, 90, 842, 842, 854, 857, 846, 846, 97, 97, /* 420 */ 98, 98, 98, 98, 296, 96, 96, 96, 96, 95, - /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 957, - /* 440 */ 957, 158, 25, 422, 99, 100, 90, 978, 978, 853, - /* 450 */ 856, 845, 845, 97, 97, 98, 98, 98, 98, 450, + /* 430 */ 95, 94, 94, 94, 93, 351, 325, 419, 231, 958, + /* 440 */ 958, 158, 25, 422, 99, 100, 90, 842, 842, 854, + /* 450 */ 857, 846, 846, 97, 97, 98, 98, 98, 98, 450, /* 460 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 470 */ 351, 443, 224, 224, 420, 957, 957, 961, 325, 52, - /* 480 */ 52, 958, 959, 176, 415, 78, 99, 100, 90, 978, - /* 490 */ 978, 853, 856, 845, 845, 97, 97, 98, 98, 98, + /* 470 */ 351, 443, 224, 224, 420, 958, 958, 962, 325, 52, + /* 480 */ 52, 959, 960, 176, 415, 78, 99, 100, 90, 842, + /* 490 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, /* 500 */ 98, 379, 96, 96, 96, 96, 95, 95, 94, 94, - /* 510 */ 94, 93, 351, 325, 428, 418, 298, 958, 959, 961, - /* 520 */ 81, 99, 88, 90, 978, 978, 853, 856, 845, 845, + /* 510 */ 94, 93, 351, 325, 428, 418, 298, 959, 960, 962, + /* 520 */ 81, 99, 88, 90, 842, 842, 854, 857, 846, 846, /* 530 */ 97, 97, 98, 98, 98, 98, 717, 96, 96, 96, - /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 842, - /* 550 */ 842, 854, 857, 996, 318, 343, 379, 100, 90, 978, - /* 560 */ 978, 853, 856, 845, 845, 97, 97, 98, 98, 98, + /* 540 */ 96, 95, 95, 94, 94, 94, 93, 351, 325, 843, + /* 550 */ 843, 855, 858, 996, 318, 343, 379, 100, 90, 842, + /* 560 */ 842, 854, 857, 846, 846, 97, 97, 98, 98, 98, /* 570 */ 98, 450, 96, 96, 96, 96, 95, 95, 94, 94, /* 580 */ 94, 93, 351, 325, 350, 350, 350, 260, 377, 340, - /* 590 */ 928, 52, 52, 90, 978, 978, 853, 856, 845, 845, + /* 590 */ 929, 52, 52, 90, 842, 842, 854, 857, 846, 846, /* 600 */ 97, 97, 98, 98, 98, 98, 361, 96, 96, 96, /* 610 */ 96, 95, 95, 94, 94, 94, 93, 351, 86, 445, - /* 620 */ 846, 3, 1202, 361, 360, 378, 344, 813, 957, 957, - /* 630 */ 1299, 86, 445, 729, 3, 212, 169, 287, 405, 282, + /* 620 */ 847, 3, 1203, 361, 360, 378, 344, 813, 958, 958, + /* 630 */ 1300, 86, 445, 729, 3, 212, 169, 287, 405, 282, /* 640 */ 404, 199, 232, 450, 300, 760, 83, 84, 280, 245, /* 650 */ 262, 365, 251, 85, 352, 352, 92, 89, 178, 83, /* 660 */ 84, 242, 412, 52, 52, 448, 85, 352, 352, 246, - /* 670 */ 958, 959, 194, 455, 670, 402, 399, 398, 448, 243, + /* 670 */ 959, 960, 194, 455, 670, 402, 399, 398, 448, 243, /* 680 */ 221, 114, 434, 776, 361, 450, 397, 268, 747, 224, /* 690 */ 224, 132, 132, 198, 832, 434, 452, 451, 428, 427, /* 700 */ 819, 415, 734, 713, 132, 52, 52, 832, 268, 452, - /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1270, - /* 720 */ 1270, 23, 957, 957, 86, 445, 397, 3, 228, 429, - /* 730 */ 894, 824, 824, 826, 827, 19, 203, 720, 52, 52, + /* 710 */ 451, 734, 194, 819, 363, 402, 399, 398, 450, 1271, + /* 720 */ 1271, 23, 958, 958, 86, 445, 397, 3, 228, 429, + /* 730 */ 895, 824, 824, 826, 827, 19, 203, 720, 52, 52, /* 740 */ 428, 408, 439, 249, 824, 824, 826, 827, 19, 229, /* 750 */ 403, 153, 83, 84, 761, 177, 241, 450, 721, 85, - /* 760 */ 352, 352, 120, 157, 958, 959, 58, 976, 409, 355, + /* 760 */ 352, 352, 120, 157, 959, 960, 58, 977, 409, 355, /* 770 */ 330, 448, 268, 428, 430, 320, 790, 32, 32, 86, /* 780 */ 445, 776, 3, 341, 98, 98, 98, 98, 434, 96, /* 790 */ 96, 96, 96, 95, 95, 94, 94, 94, 93, 351, - /* 800 */ 832, 120, 452, 451, 813, 886, 819, 83, 84, 976, - /* 810 */ 813, 132, 410, 919, 85, 352, 352, 132, 407, 789, - /* 820 */ 957, 957, 92, 89, 178, 916, 448, 262, 370, 261, - /* 830 */ 82, 913, 80, 262, 370, 261, 776, 824, 824, 826, - /* 840 */ 827, 19, 933, 434, 96, 96, 96, 96, 95, 95, - /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 957, - /* 860 */ 957, 819, 958, 959, 120, 92, 89, 178, 944, 2, - /* 870 */ 917, 964, 268, 1, 975, 76, 445, 762, 3, 708, - /* 880 */ 900, 900, 387, 957, 957, 757, 918, 371, 740, 778, + /* 800 */ 832, 120, 452, 451, 813, 887, 819, 83, 84, 977, + /* 810 */ 813, 132, 410, 920, 85, 352, 352, 132, 407, 789, + /* 820 */ 958, 958, 92, 89, 178, 917, 448, 262, 370, 261, + /* 830 */ 82, 914, 80, 262, 370, 261, 776, 824, 824, 826, + /* 840 */ 827, 19, 934, 434, 96, 96, 96, 96, 95, 95, + /* 850 */ 94, 94, 94, 93, 351, 832, 74, 452, 451, 958, + /* 860 */ 958, 819, 959, 960, 120, 92, 89, 178, 945, 2, + /* 870 */ 918, 965, 268, 1, 976, 76, 445, 762, 3, 708, + /* 880 */ 901, 901, 387, 958, 958, 757, 919, 371, 740, 778, /* 890 */ 756, 257, 824, 824, 826, 827, 19, 417, 741, 450, - /* 900 */ 24, 958, 959, 83, 84, 369, 957, 957, 177, 226, - /* 910 */ 85, 352, 352, 884, 315, 314, 313, 215, 311, 10, - /* 920 */ 10, 683, 448, 349, 348, 958, 959, 908, 777, 157, - /* 930 */ 120, 957, 957, 337, 776, 416, 711, 310, 450, 434, - /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 958, 959, - /* 950 */ 907, 832, 792, 452, 451, 9, 9, 819, 10, 10, + /* 900 */ 24, 959, 960, 83, 84, 369, 958, 958, 177, 226, + /* 910 */ 85, 352, 352, 885, 315, 314, 313, 215, 311, 10, + /* 920 */ 10, 683, 448, 349, 348, 959, 960, 909, 777, 157, + /* 930 */ 120, 958, 958, 337, 776, 416, 711, 310, 450, 434, + /* 940 */ 450, 321, 450, 791, 103, 200, 175, 450, 959, 960, + /* 950 */ 908, 832, 792, 452, 451, 9, 9, 819, 10, 10, /* 960 */ 52, 52, 51, 51, 180, 716, 248, 10, 10, 171, - /* 970 */ 170, 167, 339, 958, 959, 247, 984, 702, 702, 450, - /* 980 */ 715, 233, 686, 982, 888, 983, 182, 913, 824, 824, + /* 970 */ 170, 167, 339, 959, 960, 247, 984, 702, 702, 450, + /* 980 */ 715, 233, 686, 982, 889, 983, 182, 914, 824, 824, /* 990 */ 826, 827, 19, 183, 256, 423, 132, 181, 394, 10, - /* 1000 */ 10, 888, 890, 749, 957, 957, 916, 268, 985, 198, + /* 1000 */ 10, 889, 891, 749, 958, 958, 917, 268, 985, 198, /* 1010 */ 985, 349, 348, 425, 415, 299, 817, 832, 326, 825, /* 1020 */ 120, 332, 133, 819, 268, 98, 98, 98, 98, 91, /* 1030 */ 96, 96, 96, 96, 95, 95, 94, 94, 94, 93, - /* 1040 */ 351, 157, 810, 371, 382, 359, 958, 959, 358, 268, - /* 1050 */ 450, 917, 368, 324, 824, 824, 826, 450, 709, 450, - /* 1060 */ 264, 380, 888, 450, 876, 746, 253, 918, 255, 433, + /* 1040 */ 351, 157, 810, 371, 382, 359, 959, 960, 358, 268, + /* 1050 */ 450, 918, 368, 324, 824, 824, 826, 450, 709, 450, + /* 1060 */ 264, 380, 889, 450, 877, 746, 253, 919, 255, 433, /* 1070 */ 36, 36, 234, 450, 234, 120, 269, 37, 37, 12, /* 1080 */ 12, 334, 272, 27, 27, 450, 330, 118, 450, 162, /* 1090 */ 742, 280, 450, 38, 38, 450, 985, 356, 985, 450, - /* 1100 */ 709, 1209, 450, 132, 450, 39, 39, 450, 40, 40, + /* 1100 */ 709, 1210, 450, 132, 450, 39, 39, 450, 40, 40, /* 1110 */ 450, 362, 41, 41, 450, 42, 42, 450, 254, 28, /* 1120 */ 28, 450, 29, 29, 31, 31, 450, 43, 43, 450, /* 1130 */ 44, 44, 450, 714, 45, 45, 450, 11, 11, 767, /* 1140 */ 450, 46, 46, 450, 268, 450, 105, 105, 450, 47, /* 1150 */ 47, 450, 48, 48, 450, 237, 33, 33, 450, 172, /* 1160 */ 49, 49, 450, 50, 50, 34, 34, 274, 122, 122, - /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 897, 56, 56, - /* 1180 */ 450, 896, 35, 35, 450, 267, 450, 817, 450, 817, + /* 1170 */ 450, 123, 123, 450, 124, 124, 450, 898, 56, 56, + /* 1180 */ 450, 897, 35, 35, 450, 267, 450, 817, 450, 817, /* 1190 */ 106, 106, 450, 53, 53, 385, 107, 107, 450, 817, /* 1200 */ 108, 108, 817, 450, 104, 104, 121, 121, 119, 119, /* 1210 */ 450, 117, 112, 112, 450, 276, 450, 225, 111, 111, - /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 911, + /* 1220 */ 450, 730, 450, 109, 109, 450, 673, 674, 675, 912, /* 1230 */ 110, 110, 317, 998, 55, 55, 57, 57, 692, 331, - /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 936, 197, + /* 1240 */ 54, 54, 26, 26, 696, 30, 30, 317, 937, 197, /* 1250 */ 196, 195, 335, 281, 336, 446, 331, 745, 689, 436, - /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 932, + /* 1260 */ 440, 444, 120, 72, 386, 223, 175, 345, 757, 933, /* 1270 */ 20, 286, 319, 756, 815, 372, 374, 202, 202, 202, - /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 883, + /* 1280 */ 263, 395, 285, 74, 208, 21, 696, 719, 718, 884, /* 1290 */ 120, 120, 120, 120, 120, 754, 278, 828, 77, 74, - /* 1300 */ 726, 727, 785, 783, 879, 202, 999, 208, 893, 892, - /* 1310 */ 893, 892, 694, 816, 763, 116, 774, 1289, 431, 432, + /* 1300 */ 726, 727, 785, 783, 880, 202, 999, 208, 894, 893, + /* 1310 */ 894, 893, 694, 816, 763, 116, 774, 1290, 431, 432, /* 1320 */ 302, 999, 390, 303, 823, 697, 691, 680, 159, 289, - /* 1330 */ 679, 883, 681, 951, 291, 218, 293, 7, 316, 828, - /* 1340 */ 173, 805, 259, 364, 252, 910, 376, 713, 295, 435, - /* 1350 */ 308, 168, 954, 993, 135, 400, 990, 284, 881, 880, - /* 1360 */ 205, 927, 925, 59, 333, 62, 144, 156, 130, 72, + /* 1330 */ 679, 884, 681, 952, 291, 218, 293, 7, 316, 828, + /* 1340 */ 173, 805, 259, 364, 252, 911, 376, 713, 295, 435, + /* 1350 */ 308, 168, 955, 993, 135, 400, 990, 284, 882, 881, + /* 1360 */ 205, 928, 926, 59, 333, 62, 144, 156, 130, 72, /* 1370 */ 802, 366, 367, 393, 137, 185, 189, 160, 139, 383, - /* 1380 */ 67, 895, 140, 141, 142, 148, 389, 812, 775, 266, - /* 1390 */ 219, 190, 154, 391, 912, 875, 271, 406, 191, 322, + /* 1380 */ 67, 896, 140, 141, 142, 148, 389, 812, 775, 266, + /* 1390 */ 219, 190, 154, 391, 913, 876, 271, 406, 191, 322, /* 1400 */ 682, 733, 192, 342, 732, 724, 731, 711, 723, 421, /* 1410 */ 705, 71, 323, 6, 204, 771, 288, 79, 297, 346, - /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 966, 239, - /* 1430 */ 769, 102, 861, 438, 426, 240, 424, 442, 73, 213, - /* 1440 */ 688, 238, 22, 453, 952, 214, 217, 216, 454, 677, + /* 1420 */ 772, 704, 290, 283, 703, 770, 292, 294, 967, 239, + /* 1430 */ 769, 102, 862, 438, 426, 240, 424, 442, 73, 213, + /* 1440 */ 688, 238, 22, 453, 953, 214, 217, 216, 454, 677, /* 1450 */ 676, 671, 753, 125, 115, 235, 126, 669, 353, 166, - /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 891, - /* 1470 */ 327, 889, 811, 328, 134, 128, 136, 138, 743, 258, - /* 1480 */ 906, 184, 143, 129, 909, 186, 63, 64, 145, 187, - /* 1490 */ 905, 65, 8, 66, 13, 188, 202, 898, 265, 149, + /* 1460 */ 127, 244, 179, 357, 306, 304, 305, 307, 113, 892, + /* 1470 */ 327, 890, 811, 328, 134, 128, 136, 138, 743, 258, + /* 1480 */ 907, 184, 143, 129, 910, 186, 63, 64, 145, 187, + /* 1490 */ 906, 65, 8, 66, 13, 188, 202, 899, 265, 149, /* 1500 */ 987, 388, 150, 685, 161, 392, 285, 193, 279, 396, /* 1510 */ 151, 401, 68, 14, 15, 722, 69, 236, 831, 131, - /* 1520 */ 830, 859, 70, 751, 16, 414, 755, 4, 174, 220, - /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 874, - /* 1540 */ 860, 858, 915, 863, 914, 207, 206, 941, 163, 437, - /* 1550 */ 947, 942, 164, 209, 1002, 441, 862, 165, 210, 829, - /* 1560 */ 695, 87, 312, 211, 1291, 1290, 309, + /* 1520 */ 830, 860, 70, 751, 16, 414, 755, 4, 174, 220, + /* 1530 */ 222, 784, 201, 152, 779, 77, 74, 17, 18, 875, + /* 1540 */ 861, 859, 916, 864, 915, 207, 206, 942, 163, 437, + /* 1550 */ 948, 943, 164, 209, 1002, 441, 863, 165, 210, 829, + /* 1560 */ 695, 87, 312, 211, 1292, 1291, 309, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 19, 95, 53, 97, 22, 24, 24, 101, 27, 28, /* 10 */ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 20 */ 39, 40, 41, 152, 43, 44, 45, 46, 47, 48, @@ -135633,55 +133587,55 @@ /* 300 */ 1256, 1200, 1206, 1260, 1247, 1261, 1263, 1262, 1266, 1278, /* 310 */ 1282, 1292, 1294, 1297, 1298, 1299, 1300, 1221, 1224, 1228, /* 320 */ 1288, 1291, 1276, 1277, 1295, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1280, 1270, 1270, 1270, 1202, 1202, 1202, 1202, 1270, 1096, - /* 10 */ 1125, 1125, 1254, 1332, 1332, 1332, 1332, 1332, 1332, 1201, - /* 20 */ 1332, 1332, 1332, 1332, 1270, 1100, 1131, 1332, 1332, 1332, - /* 30 */ 1332, 1203, 1204, 1332, 1332, 1332, 1253, 1255, 1141, 1140, - /* 40 */ 1139, 1138, 1236, 1112, 1136, 1129, 1133, 1203, 1197, 1198, - /* 50 */ 1196, 1200, 1204, 1332, 1132, 1167, 1181, 1166, 1332, 1332, + /* 0 */ 1281, 1271, 1271, 1271, 1203, 1203, 1203, 1203, 1271, 1096, + /* 10 */ 1125, 1125, 1255, 1332, 1332, 1332, 1332, 1332, 1332, 1202, + /* 20 */ 1332, 1332, 1332, 1332, 1271, 1100, 1131, 1332, 1332, 1332, + /* 30 */ 1332, 1204, 1205, 1332, 1332, 1332, 1254, 1256, 1141, 1140, + /* 40 */ 1139, 1138, 1237, 1112, 1136, 1129, 1133, 1204, 1198, 1199, + /* 50 */ 1197, 1201, 1205, 1332, 1132, 1167, 1182, 1166, 1332, 1332, /* 60 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 70 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 80 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 90 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 100 */ 1332, 1332, 1332, 1332, 1175, 1180, 1187, 1179, 1176, 1169, + /* 100 */ 1332, 1332, 1332, 1332, 1176, 1181, 1188, 1180, 1177, 1169, /* 110 */ 1168, 1170, 1171, 1332, 1019, 1067, 1332, 1332, 1332, 1172, - /* 120 */ 1332, 1173, 1184, 1183, 1182, 1261, 1288, 1287, 1332, 1332, + /* 120 */ 1332, 1173, 1185, 1184, 1183, 1262, 1289, 1288, 1332, 1332, /* 130 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 140 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 150 */ 1332, 1332, 1332, 1332, 1332, 1280, 1270, 1025, 1025, 1332, - /* 160 */ 1270, 1270, 1270, 1270, 1270, 1270, 1266, 1100, 1091, 1332, + /* 150 */ 1332, 1332, 1332, 1332, 1332, 1281, 1271, 1025, 1025, 1332, + /* 160 */ 1271, 1271, 1271, 1271, 1271, 1271, 1267, 1100, 1091, 1332, /* 170 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 180 */ 1258, 1256, 1332, 1217, 1332, 1332, 1332, 1332, 1332, 1332, + /* 180 */ 1259, 1257, 1332, 1218, 1332, 1332, 1332, 1332, 1332, 1332, /* 190 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 200 */ 1332, 1332, 1332, 1332, 1096, 1332, 1332, 1332, 1332, 1332, - /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1282, 1332, 1231, + /* 210 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1283, 1332, 1232, /* 220 */ 1096, 1096, 1096, 1098, 1080, 1090, 1004, 1135, 1114, 1114, - /* 230 */ 1321, 1135, 1321, 1042, 1302, 1039, 1125, 1114, 1199, 1125, + /* 230 */ 1321, 1135, 1321, 1042, 1303, 1039, 1125, 1114, 1200, 1125, /* 240 */ 1125, 1097, 1090, 1332, 1324, 1105, 1105, 1323, 1323, 1105, /* 250 */ 1146, 1070, 1135, 1076, 1076, 1076, 1076, 1105, 1016, 1135, - /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1235, 1318, 1105, 1105, - /* 270 */ 1016, 1210, 1105, 1016, 1105, 1016, 1210, 1068, 1068, 1068, - /* 280 */ 1057, 1210, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, - /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1205, 1105, 1332, - /* 300 */ 1210, 1214, 1214, 1210, 1130, 1119, 1128, 1126, 1135, 1022, - /* 310 */ 1060, 1285, 1285, 1281, 1281, 1281, 1281, 1329, 1329, 1266, - /* 320 */ 1297, 1297, 1044, 1044, 1297, 1332, 1332, 1332, 1332, 1332, - /* 330 */ 1332, 1292, 1332, 1219, 1332, 1332, 1332, 1332, 1332, 1332, + /* 260 */ 1146, 1070, 1070, 1135, 1105, 1016, 1236, 1318, 1105, 1105, + /* 270 */ 1016, 1211, 1105, 1016, 1105, 1016, 1211, 1068, 1068, 1068, + /* 280 */ 1057, 1211, 1068, 1042, 1068, 1057, 1068, 1068, 1118, 1113, + /* 290 */ 1118, 1113, 1118, 1113, 1118, 1113, 1105, 1206, 1105, 1332, + /* 300 */ 1211, 1215, 1215, 1211, 1130, 1119, 1128, 1126, 1135, 1022, + /* 310 */ 1060, 1286, 1286, 1282, 1282, 1282, 1282, 1329, 1329, 1267, + /* 320 */ 1298, 1298, 1044, 1044, 1298, 1332, 1332, 1332, 1332, 1332, + /* 330 */ 1332, 1293, 1332, 1220, 1332, 1332, 1332, 1332, 1332, 1332, /* 340 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 350 */ 1332, 1332, 1152, 1332, 1000, 1263, 1332, 1332, 1262, 1332, + /* 350 */ 1332, 1332, 1152, 1332, 1000, 1264, 1332, 1332, 1263, 1332, /* 360 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 370 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1320, - /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1234, 1233, 1332, 1332, + /* 380 */ 1332, 1332, 1332, 1332, 1332, 1332, 1235, 1234, 1332, 1332, /* 390 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, /* 400 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, - /* 410 */ 1332, 1082, 1332, 1332, 1332, 1306, 1332, 1332, 1332, 1332, + /* 410 */ 1332, 1082, 1332, 1332, 1332, 1307, 1332, 1332, 1332, 1332, /* 420 */ 1332, 1332, 1332, 1127, 1332, 1120, 1332, 1332, 1311, 1332, - /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1272, - /* 440 */ 1332, 1332, 1332, 1271, 1332, 1332, 1332, 1332, 1332, 1154, + /* 430 */ 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1332, 1273, + /* 440 */ 1332, 1332, 1332, 1272, 1332, 1332, 1332, 1332, 1332, 1154, /* 450 */ 1332, 1153, 1157, 1332, 1010, 1332, }; /********** End of lemon-generated parsing tables *****************************/ /* The next table maps tokens (terminal symbols) into fallback tokens. @@ -136123,147 +134077,147 @@ /* 169 */ "expr ::= expr EQ|NE expr", /* 170 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", /* 171 */ "expr ::= expr PLUS|MINUS expr", /* 172 */ "expr ::= expr STAR|SLASH|REM expr", /* 173 */ "expr ::= expr CONCAT expr", - /* 174 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 175 */ "expr ::= expr likeop expr", - /* 176 */ "expr ::= expr likeop expr ESCAPE expr", - /* 177 */ "expr ::= expr ISNULL|NOTNULL", - /* 178 */ "expr ::= expr NOT NULL", - /* 179 */ "expr ::= expr IS expr", - /* 180 */ "expr ::= expr IS NOT expr", - /* 181 */ "expr ::= NOT expr", - /* 182 */ "expr ::= BITNOT expr", - /* 183 */ "expr ::= MINUS expr", - /* 184 */ "expr ::= PLUS expr", - /* 185 */ "between_op ::= BETWEEN", - /* 186 */ "between_op ::= NOT BETWEEN", - /* 187 */ "expr ::= expr between_op expr AND expr", - /* 188 */ "in_op ::= IN", - /* 189 */ "in_op ::= NOT IN", - /* 190 */ "expr ::= expr in_op LP exprlist RP", - /* 191 */ "expr ::= LP select RP", - /* 192 */ "expr ::= expr in_op LP select RP", - /* 193 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 194 */ "expr ::= EXISTS LP select RP", - /* 195 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 196 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 197 */ "case_exprlist ::= WHEN expr THEN expr", - /* 198 */ "case_else ::= ELSE expr", - /* 199 */ "case_else ::=", - /* 200 */ "case_operand ::= expr", - /* 201 */ "case_operand ::=", - /* 202 */ "exprlist ::=", - /* 203 */ "nexprlist ::= nexprlist COMMA expr", - /* 204 */ "nexprlist ::= expr", - /* 205 */ "paren_exprlist ::=", - /* 206 */ "paren_exprlist ::= LP exprlist RP", - /* 207 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 208 */ "uniqueflag ::= UNIQUE", - /* 209 */ "uniqueflag ::=", - /* 210 */ "eidlist_opt ::=", - /* 211 */ "eidlist_opt ::= LP eidlist RP", - /* 212 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 213 */ "eidlist ::= nm collate sortorder", - /* 214 */ "collate ::=", - /* 215 */ "collate ::= COLLATE ID|STRING", - /* 216 */ "cmd ::= DROP INDEX ifexists fullname", - /* 217 */ "cmd ::= VACUUM", - /* 218 */ "cmd ::= VACUUM nm", - /* 219 */ "cmd ::= PRAGMA nm dbnm", - /* 220 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 221 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 222 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 223 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 224 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 225 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 226 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 227 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 228 */ "trigger_time ::= BEFORE", - /* 229 */ "trigger_time ::= AFTER", - /* 230 */ "trigger_time ::= INSTEAD OF", - /* 231 */ "trigger_time ::=", - /* 232 */ "trigger_event ::= DELETE|INSERT", - /* 233 */ "trigger_event ::= UPDATE", - /* 234 */ "trigger_event ::= UPDATE OF idlist", - /* 235 */ "when_clause ::=", - /* 236 */ "when_clause ::= WHEN expr", - /* 237 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 238 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 239 */ "trnm ::= nm DOT nm", - /* 240 */ "tridxby ::= INDEXED BY nm", - /* 241 */ "tridxby ::= NOT INDEXED", - /* 242 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 243 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", - /* 244 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 245 */ "trigger_cmd ::= select", - /* 246 */ "expr ::= RAISE LP IGNORE RP", - /* 247 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 248 */ "raisetype ::= ROLLBACK", - /* 249 */ "raisetype ::= ABORT", - /* 250 */ "raisetype ::= FAIL", - /* 251 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 252 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 253 */ "cmd ::= DETACH database_kw_opt expr", - /* 254 */ "key_opt ::=", - /* 255 */ "key_opt ::= KEY expr", - /* 256 */ "cmd ::= REINDEX", - /* 257 */ "cmd ::= REINDEX nm dbnm", - /* 258 */ "cmd ::= ANALYZE", - /* 259 */ "cmd ::= ANALYZE nm dbnm", - /* 260 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 261 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 262 */ "add_column_fullname ::= fullname", - /* 263 */ "cmd ::= create_vtab", - /* 264 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 265 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 266 */ "vtabarg ::=", - /* 267 */ "vtabargtoken ::= ANY", - /* 268 */ "vtabargtoken ::= lp anylist RP", - /* 269 */ "lp ::= LP", - /* 270 */ "with ::=", - /* 271 */ "with ::= WITH wqlist", - /* 272 */ "with ::= WITH RECURSIVE wqlist", - /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", - /* 275 */ "input ::= cmdlist", - /* 276 */ "cmdlist ::= cmdlist ecmd", - /* 277 */ "cmdlist ::= ecmd", - /* 278 */ "ecmd ::= SEMI", - /* 279 */ "ecmd ::= explain cmdx SEMI", - /* 280 */ "explain ::=", - /* 281 */ "trans_opt ::=", - /* 282 */ "trans_opt ::= TRANSACTION", - /* 283 */ "trans_opt ::= TRANSACTION nm", - /* 284 */ "savepoint_opt ::= SAVEPOINT", - /* 285 */ "savepoint_opt ::=", - /* 286 */ "cmd ::= create_table create_table_args", - /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 288 */ "columnlist ::= columnname carglist", - /* 289 */ "nm ::= ID|INDEXED", - /* 290 */ "nm ::= STRING", - /* 291 */ "nm ::= JOIN_KW", - /* 292 */ "typetoken ::= typename", - /* 293 */ "typename ::= ID|STRING", - /* 294 */ "signed ::= plus_num", - /* 295 */ "signed ::= minus_num", - /* 296 */ "carglist ::= carglist ccons", - /* 297 */ "carglist ::=", - /* 298 */ "ccons ::= NULL onconf", - /* 299 */ "conslist_opt ::= COMMA conslist", - /* 300 */ "conslist ::= conslist tconscomma tcons", - /* 301 */ "conslist ::= tcons", - /* 302 */ "tconscomma ::=", - /* 303 */ "defer_subclause_opt ::= defer_subclause", - /* 304 */ "resolvetype ::= raisetype", - /* 305 */ "selectnowith ::= oneselect", - /* 306 */ "oneselect ::= values", - /* 307 */ "sclp ::= selcollist COMMA", - /* 308 */ "as ::= ID|STRING", - /* 309 */ "expr ::= term", - /* 310 */ "likeop ::= LIKE_KW|MATCH", + /* 174 */ "likeop ::= LIKE_KW|MATCH", + /* 175 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 176 */ "expr ::= expr likeop expr", + /* 177 */ "expr ::= expr likeop expr ESCAPE expr", + /* 178 */ "expr ::= expr ISNULL|NOTNULL", + /* 179 */ "expr ::= expr NOT NULL", + /* 180 */ "expr ::= expr IS expr", + /* 181 */ "expr ::= expr IS NOT expr", + /* 182 */ "expr ::= NOT expr", + /* 183 */ "expr ::= BITNOT expr", + /* 184 */ "expr ::= MINUS expr", + /* 185 */ "expr ::= PLUS expr", + /* 186 */ "between_op ::= BETWEEN", + /* 187 */ "between_op ::= NOT BETWEEN", + /* 188 */ "expr ::= expr between_op expr AND expr", + /* 189 */ "in_op ::= IN", + /* 190 */ "in_op ::= NOT IN", + /* 191 */ "expr ::= expr in_op LP exprlist RP", + /* 192 */ "expr ::= LP select RP", + /* 193 */ "expr ::= expr in_op LP select RP", + /* 194 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 195 */ "expr ::= EXISTS LP select RP", + /* 196 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 197 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 198 */ "case_exprlist ::= WHEN expr THEN expr", + /* 199 */ "case_else ::= ELSE expr", + /* 200 */ "case_else ::=", + /* 201 */ "case_operand ::= expr", + /* 202 */ "case_operand ::=", + /* 203 */ "exprlist ::=", + /* 204 */ "nexprlist ::= nexprlist COMMA expr", + /* 205 */ "nexprlist ::= expr", + /* 206 */ "paren_exprlist ::=", + /* 207 */ "paren_exprlist ::= LP exprlist RP", + /* 208 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 209 */ "uniqueflag ::= UNIQUE", + /* 210 */ "uniqueflag ::=", + /* 211 */ "eidlist_opt ::=", + /* 212 */ "eidlist_opt ::= LP eidlist RP", + /* 213 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 214 */ "eidlist ::= nm collate sortorder", + /* 215 */ "collate ::=", + /* 216 */ "collate ::= COLLATE ID|STRING", + /* 217 */ "cmd ::= DROP INDEX ifexists fullname", + /* 218 */ "cmd ::= VACUUM", + /* 219 */ "cmd ::= VACUUM nm", + /* 220 */ "cmd ::= PRAGMA nm dbnm", + /* 221 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 222 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 223 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 224 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 225 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 226 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 227 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 228 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 229 */ "trigger_time ::= BEFORE", + /* 230 */ "trigger_time ::= AFTER", + /* 231 */ "trigger_time ::= INSTEAD OF", + /* 232 */ "trigger_time ::=", + /* 233 */ "trigger_event ::= DELETE|INSERT", + /* 234 */ "trigger_event ::= UPDATE", + /* 235 */ "trigger_event ::= UPDATE OF idlist", + /* 236 */ "when_clause ::=", + /* 237 */ "when_clause ::= WHEN expr", + /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 240 */ "trnm ::= nm DOT nm", + /* 241 */ "tridxby ::= INDEXED BY nm", + /* 242 */ "tridxby ::= NOT INDEXED", + /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 244 */ "trigger_cmd ::= insert_cmd INTO trnm idlist_opt select", + /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 246 */ "trigger_cmd ::= select", + /* 247 */ "expr ::= RAISE LP IGNORE RP", + /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 249 */ "raisetype ::= ROLLBACK", + /* 250 */ "raisetype ::= ABORT", + /* 251 */ "raisetype ::= FAIL", + /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 254 */ "cmd ::= DETACH database_kw_opt expr", + /* 255 */ "key_opt ::=", + /* 256 */ "key_opt ::= KEY expr", + /* 257 */ "cmd ::= REINDEX", + /* 258 */ "cmd ::= REINDEX nm dbnm", + /* 259 */ "cmd ::= ANALYZE", + /* 260 */ "cmd ::= ANALYZE nm dbnm", + /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 263 */ "add_column_fullname ::= fullname", + /* 264 */ "cmd ::= create_vtab", + /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 267 */ "vtabarg ::=", + /* 268 */ "vtabargtoken ::= ANY", + /* 269 */ "vtabargtoken ::= lp anylist RP", + /* 270 */ "lp ::= LP", + /* 271 */ "with ::=", + /* 272 */ "with ::= WITH wqlist", + /* 273 */ "with ::= WITH RECURSIVE wqlist", + /* 274 */ "wqlist ::= nm eidlist_opt AS LP select RP", + /* 275 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 276 */ "input ::= cmdlist", + /* 277 */ "cmdlist ::= cmdlist ecmd", + /* 278 */ "cmdlist ::= ecmd", + /* 279 */ "ecmd ::= SEMI", + /* 280 */ "ecmd ::= explain cmdx SEMI", + /* 281 */ "explain ::=", + /* 282 */ "trans_opt ::=", + /* 283 */ "trans_opt ::= TRANSACTION", + /* 284 */ "trans_opt ::= TRANSACTION nm", + /* 285 */ "savepoint_opt ::= SAVEPOINT", + /* 286 */ "savepoint_opt ::=", + /* 287 */ "cmd ::= create_table create_table_args", + /* 288 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 289 */ "columnlist ::= columnname carglist", + /* 290 */ "nm ::= ID|INDEXED", + /* 291 */ "nm ::= STRING", + /* 292 */ "nm ::= JOIN_KW", + /* 293 */ "typetoken ::= typename", + /* 294 */ "typename ::= ID|STRING", + /* 295 */ "signed ::= plus_num", + /* 296 */ "signed ::= minus_num", + /* 297 */ "carglist ::= carglist ccons", + /* 298 */ "carglist ::=", + /* 299 */ "ccons ::= NULL onconf", + /* 300 */ "conslist_opt ::= COMMA conslist", + /* 301 */ "conslist ::= conslist tconscomma tcons", + /* 302 */ "conslist ::= tcons", + /* 303 */ "tconscomma ::=", + /* 304 */ "defer_subclause_opt ::= defer_subclause", + /* 305 */ "resolvetype ::= raisetype", + /* 306 */ "selectnowith ::= oneselect", + /* 307 */ "oneselect ::= values", + /* 308 */ "sclp ::= selcollist COMMA", + /* 309 */ "as ::= ID|STRING", + /* 310 */ "expr ::= term", /* 311 */ "exprlist ::= nexprlist", /* 312 */ "nmnum ::= plus_num", /* 313 */ "nmnum ::= nm", /* 314 */ "nmnum ::= ON", /* 315 */ "nmnum ::= DELETE", @@ -136327,35 +134281,10 @@ */ #ifndef YYMALLOCARGTYPE # define YYMALLOCARGTYPE size_t #endif -/* Initialize a new parser that has already been allocated. -*/ -SQLITE_PRIVATE void sqlite3ParserInit(void *yypParser){ - yyParser *pParser = (yyParser*)yypParser; -#ifdef YYTRACKMAXSTACKDEPTH - pParser->yyhwm = 0; -#endif -#if YYSTACKDEPTH<=0 - pParser->yytos = NULL; - pParser->yystack = NULL; - pParser->yystksz = 0; - if( yyGrowStack(pParser) ){ - pParser->yystack = &pParser->yystk0; - pParser->yystksz = 1; - } -#endif -#ifndef YYNOERRORRECOVERY - pParser->yyerrcnt = -1; -#endif - pParser->yytos = pParser->yystack; - pParser->yystack[0].stateno = 0; - pParser->yystack[0].major = 0; -} - -#ifndef sqlite3Parser_ENGINEALWAYSONSTACK /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** @@ -136367,15 +134296,32 @@ ** to sqlite3Parser and sqlite3ParserFree. */ SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ yyParser *pParser; pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); - if( pParser ) sqlite3ParserInit(pParser); + if( pParser ){ +#ifdef YYTRACKMAXSTACKDEPTH + pParser->yyhwm = 0; +#endif +#if YYSTACKDEPTH<=0 + pParser->yytos = NULL; + pParser->yystack = NULL; + pParser->yystksz = 0; + if( yyGrowStack(pParser) ){ + pParser->yystack = &pParser->yystk0; + pParser->yystksz = 1; + } +#endif +#ifndef YYNOERRORRECOVERY + pParser->yyerrcnt = -1; +#endif + pParser->yytos = pParser->yystack; + pParser->yystack[0].stateno = 0; + pParser->yystack[0].major = 0; + } return pParser; } -#endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ - /* The following function deletes the "minor type" or semantic value ** associated with a symbol. The symbol can be either a terminal ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is ** a pointer to the value to be deleted. The code used to do the @@ -136497,22 +134443,10 @@ } #endif yy_destructor(pParser, yytos->major, &yytos->minor); } -/* -** Clear all secondary memory allocations from the parser -*/ -SQLITE_PRIVATE void sqlite3ParserFinalize(void *p){ - yyParser *pParser = (yyParser*)p; - while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); -#if YYSTACKDEPTH<=0 - if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); -#endif -} - -#ifndef sqlite3Parser_ENGINEALWAYSONSTACK /* ** Deallocate and destroy a parser. Destructors are called for ** all stack elements before shutting the parser down. ** ** If the YYPARSEFREENEVERNULL macro exists (for example because it @@ -136521,17 +134455,20 @@ */ SQLITE_PRIVATE void sqlite3ParserFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ + yyParser *pParser = (yyParser*)p; #ifndef YYPARSEFREENEVERNULL - if( p==0 ) return; + if( pParser==0 ) return; #endif - sqlite3ParserFinalize(p); - (*freeProc)(p); + while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); +#endif + (*freeProc)((void*)pParser); } -#endif /* sqlite3Parser_ENGINEALWAYSONSTACK */ /* ** Return the peak depth of the stack for a parser. */ #ifdef YYTRACKMAXSTACKDEPTH @@ -136638,10 +134575,11 @@ /* ** The following routine is called if the stack overflows. */ static void yyStackOverflow(yyParser *yypParser){ sqlite3ParserARG_FETCH; + yypParser->yytos--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif @@ -136692,18 +134630,16 @@ assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); } #endif #if YYSTACKDEPTH>0 if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){ - yypParser->yytos--; yyStackOverflow(yypParser); return; } #else if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ if( yyGrowStack(yypParser) ){ - yypParser->yytos--; yyStackOverflow(yypParser); return; } } #endif @@ -136896,10 +134832,11 @@ { 173, 3 }, { 173, 3 }, { 173, 3 }, { 173, 3 }, { 173, 3 }, + { 221, 1 }, { 221, 2 }, { 173, 3 }, { 173, 5 }, { 173, 2 }, { 173, 3 }, @@ -137032,11 +134969,10 @@ { 194, 1 }, { 195, 1 }, { 209, 2 }, { 210, 1 }, { 173, 1 }, - { 221, 1 }, { 208, 1 }, { 230, 1 }, { 230, 1 }, { 230, 1 }, { 230, 1 }, @@ -137175,11 +135111,11 @@ case 42: /* autoinc ::= */ yytestcase(yyruleno==42); case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); case 76: /* ifexists ::= */ yytestcase(yyruleno==76); case 90: /* distinct ::= */ yytestcase(yyruleno==90); - case 214: /* collate ::= */ yytestcase(yyruleno==214); + case 215: /* collate ::= */ yytestcase(yyruleno==215); {yymsp[1].minor.yy194 = 0;} break; case 17: /* ifnotexists ::= IF NOT EXISTS */ {yymsp[-2].minor.yy194 = 1;} break; @@ -137241,11 +135177,11 @@ {sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);} break; case 33: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0); + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0, 0); v.zStart = yymsp[-1].minor.yy0.z; v.zEnd = yymsp[0].minor.yy190.zEnd; sqlite3AddDefaultValue(pParse,&v); } break; @@ -137319,13 +135255,13 @@ case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); {yymsp[-1].minor.yy194 = yymsp[0].minor.yy194;} break; case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); - case 186: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==186); - case 189: /* in_op ::= NOT IN */ yytestcase(yyruleno==189); - case 215: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==215); + case 187: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==187); + case 190: /* in_op ::= NOT IN */ yytestcase(yyruleno==190); + case 216: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==216); {yymsp[-1].minor.yy194 = 1;} break; case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ {yymsp[-1].minor.yy194 = 0;} break; @@ -137485,13 +135421,13 @@ {yymsp[0].minor.yy194 = SF_All;} break; case 91: /* sclp ::= */ case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); - case 202: /* exprlist ::= */ yytestcase(yyruleno==202); - case 205: /* paren_exprlist ::= */ yytestcase(yyruleno==205); - case 210: /* eidlist_opt ::= */ yytestcase(yyruleno==210); + case 203: /* exprlist ::= */ yytestcase(yyruleno==203); + case 206: /* paren_exprlist ::= */ yytestcase(yyruleno==206); + case 211: /* eidlist_opt ::= */ yytestcase(yyruleno==211); {yymsp[1].minor.yy148 = 0;} break; case 92: /* selcollist ::= sclp expr as */ { yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr); @@ -137505,20 +135441,20 @@ yymsp[-1].minor.yy148 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy148, p); } break; case 94: /* selcollist ::= sclp nm DOT STAR */ { - Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); - Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); + Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, 0); + Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot); } break; case 95: /* as ::= AS nm */ case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); - case 224: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==224); - case 225: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==225); + case 225: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==225); + case 226: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==226); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; case 97: /* from ::= */ {yymsp[1].minor.yy185 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy185));} break; @@ -137597,18 +135533,18 @@ {yymsp[-3].minor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; case 112: /* on_opt ::= ON expr */ case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); - case 198: /* case_else ::= ELSE expr */ yytestcase(yyruleno==198); + case 199: /* case_else ::= ELSE expr */ yytestcase(yyruleno==199); {yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr;} break; case 113: /* on_opt ::= */ case 128: /* having_opt ::= */ yytestcase(yyruleno==128); case 135: /* where_opt ::= */ yytestcase(yyruleno==135); - case 199: /* case_else ::= */ yytestcase(yyruleno==199); - case 201: /* case_operand ::= */ yytestcase(yyruleno==201); + case 200: /* case_else ::= */ yytestcase(yyruleno==200); + case 202: /* case_operand ::= */ yytestcase(yyruleno==202); {yymsp[1].minor.yy72 = 0;} break; case 115: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; @@ -137733,29 +135669,29 @@ case 154: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); } break; case 155: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); - Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); + Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); } break; case 158: /* term ::= INTEGER */ { yylhsminor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); yylhsminor.yy190.zStart = yymsp[0].minor.yy0.z; yylhsminor.yy190.zEnd = yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n; - if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf|EP_Resolved; + if( yylhsminor.yy190.pExpr ) yylhsminor.yy190.pExpr->flags |= EP_Leaf; } yymsp[0].minor.yy190 = yylhsminor.yy190; break; case 159: /* expr ::= VARIABLE */ { @@ -137772,11 +135708,11 @@ spanSet(&yymsp[0].minor.yy190, &t, &t); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); yymsp[0].minor.yy190.pExpr = 0; }else{ - yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + yymsp[0].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, 0); if( yymsp[0].minor.yy190.pExpr ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy190.pExpr->iTable); } } } break; @@ -137787,12 +135723,11 @@ } break; case 161: /* expr ::= CAST LP expr AS typetoken RP */ { spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, 0); + yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0); } break; case 162: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ @@ -137821,11 +135756,11 @@ yymsp[0].minor.yy190 = yylhsminor.yy190; break; case 165: /* expr ::= LP nexprlist COMMA expr RP */ { ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy148, yymsp[-1].minor.yy190.pExpr); - yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + yylhsminor.yy190.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0, 0); if( yylhsminor.yy190.pExpr ){ yylhsminor.yy190.pExpr->x.pList = pList; spanSet(&yylhsminor.yy190, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); }else{ sqlite3ExprListDelete(pParse->db, pList); @@ -137841,14 +135776,17 @@ case 171: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==171); case 172: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==172); case 173: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==173); {spanBinaryExpr(pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);} break; - case 174: /* likeop ::= NOT LIKE_KW|MATCH */ + case 174: /* likeop ::= LIKE_KW|MATCH */ +{yymsp[0].minor.yy0=yymsp[0].minor.yy0;/*A-overwrites-X*/} + break; + case 175: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 175: /* expr ::= expr likeop expr */ + case 176: /* expr ::= expr likeop expr */ { ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr); @@ -137857,11 +135795,11 @@ exprNot(pParse, bNot, &yymsp[-2].minor.yy190); yymsp[-2].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; if( yymsp[-2].minor.yy190.pExpr ) yymsp[-2].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 176: /* expr ::= expr likeop expr ESCAPE expr */ + case 177: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); @@ -137871,57 +135809,57 @@ exprNot(pParse, bNot, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; if( yymsp[-4].minor.yy190.pExpr ) yymsp[-4].minor.yy190.pExpr->flags |= EP_InfixFunc; } break; - case 177: /* expr ::= expr ISNULL|NOTNULL */ + case 178: /* expr ::= expr ISNULL|NOTNULL */ {spanUnaryPostfix(pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);} break; - case 178: /* expr ::= expr NOT NULL */ + case 179: /* expr ::= expr NOT NULL */ {spanUnaryPostfix(pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);} break; - case 179: /* expr ::= expr IS expr */ + case 180: /* expr ::= expr IS expr */ { spanBinaryExpr(pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-2].minor.yy190.pExpr, TK_ISNULL); } break; - case 180: /* expr ::= expr IS NOT expr */ + case 181: /* expr ::= expr IS NOT expr */ { spanBinaryExpr(pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yymsp[-3].minor.yy190.pExpr, TK_NOTNULL); } break; - case 181: /* expr ::= NOT expr */ - case 182: /* expr ::= BITNOT expr */ yytestcase(yyruleno==182); + case 182: /* expr ::= NOT expr */ + case 183: /* expr ::= BITNOT expr */ yytestcase(yyruleno==183); {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 183: /* expr ::= MINUS expr */ + case 184: /* expr ::= MINUS expr */ {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 184: /* expr ::= PLUS expr */ + case 185: /* expr ::= PLUS expr */ {spanUnaryPrefix(&yymsp[-1].minor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);/*A-overwrites-B*/} break; - case 185: /* between_op ::= BETWEEN */ - case 188: /* in_op ::= IN */ yytestcase(yyruleno==188); + case 186: /* between_op ::= BETWEEN */ + case 189: /* in_op ::= IN */ yytestcase(yyruleno==189); {yymsp[0].minor.yy194 = 0;} break; - case 187: /* expr ::= expr between_op expr AND expr */ + case 188: /* expr ::= expr between_op expr AND expr */ { ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0); if( yymsp[-4].minor.yy190.pExpr ){ yymsp[-4].minor.yy190.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = yymsp[0].minor.yy190.zEnd; } break; - case 190: /* expr ::= expr in_op LP exprlist RP */ + case 191: /* expr ::= expr in_op LP exprlist RP */ { if( yymsp[-1].minor.yy148==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -137929,11 +135867,11 @@ ** ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr); - yymsp[-4].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy194],1); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy194]); }else if( yymsp[-1].minor.yy148->nExpr==1 ){ /* Expressions of the form: ** ** expr1 IN (?1) ** expr1 NOT IN (?2) @@ -137956,13 +135894,13 @@ ** before now and control would have never reached this point */ if( ALWAYS(pRHS) ){ pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy194 ? TK_NE : TK_EQ, yymsp[-4].minor.yy190.pExpr, pRHS, 0); }else{ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); if( yymsp[-4].minor.yy190.pExpr ){ yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148; sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); }else{ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy148); @@ -137970,361 +135908,360 @@ exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); } yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 191: /* expr ::= LP select RP */ + case 192: /* expr ::= LP select RP */ { spanSet(&yymsp[-2].minor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + yymsp[-2].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy190.pExpr, yymsp[-1].minor.yy243); } break; - case 192: /* expr ::= expr in_op LP select RP */ + case 193: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, yymsp[-1].minor.yy243); exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 193: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 194: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); if( yymsp[0].minor.yy148 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy148); - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy190.pExpr, pSelect); exprNot(pParse, yymsp[-3].minor.yy194, &yymsp[-4].minor.yy190); yymsp[-4].minor.yy190.zEnd = yymsp[-1].minor.yy0.z ? &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n] : &yymsp[-2].minor.yy0.z[yymsp[-2].minor.yy0.n]; } break; - case 194: /* expr ::= EXISTS LP select RP */ + case 195: /* expr ::= EXISTS LP select RP */ { Expr *p; spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-B*/ - p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + p = yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy243); } break; - case 195: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 196: /* expr ::= CASE case_operand case_exprlist case_else END */ { spanSet(&yymsp[-4].minor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-C*/ - yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0); + yymsp[-4].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, 0, 0); if( yymsp[-4].minor.yy190.pExpr ){ yymsp[-4].minor.yy190.pExpr->x.pList = yymsp[-1].minor.yy72 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[-1].minor.yy72) : yymsp[-2].minor.yy148; sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy190.pExpr); }else{ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy148); sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72); } } break; - case 196: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 197: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr); yymsp[-4].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr); } break; - case 197: /* case_exprlist ::= WHEN expr THEN expr */ + case 198: /* case_exprlist ::= WHEN expr THEN expr */ { yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr); yymsp[-3].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy148, yymsp[0].minor.yy190.pExpr); } break; - case 200: /* case_operand ::= expr */ + case 201: /* case_operand ::= expr */ {yymsp[0].minor.yy72 = yymsp[0].minor.yy190.pExpr; /*A-overwrites-X*/} break; - case 203: /* nexprlist ::= nexprlist COMMA expr */ + case 204: /* nexprlist ::= nexprlist COMMA expr */ {yymsp[-2].minor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);} break; - case 204: /* nexprlist ::= expr */ + case 205: /* nexprlist ::= expr */ {yymsp[0].minor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr); /*A-overwrites-Y*/} break; - case 206: /* paren_exprlist ::= LP exprlist RP */ - case 211: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==211); + case 207: /* paren_exprlist ::= LP exprlist RP */ + case 212: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==212); {yymsp[-2].minor.yy148 = yymsp[-1].minor.yy148;} break; - case 207: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 208: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy148, yymsp[-10].minor.yy194, &yymsp[-11].minor.yy0, yymsp[0].minor.yy72, SQLITE_SO_ASC, yymsp[-8].minor.yy194, SQLITE_IDXTYPE_APPDEF); } break; - case 208: /* uniqueflag ::= UNIQUE */ - case 249: /* raisetype ::= ABORT */ yytestcase(yyruleno==249); + case 209: /* uniqueflag ::= UNIQUE */ + case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); {yymsp[0].minor.yy194 = OE_Abort;} break; - case 209: /* uniqueflag ::= */ + case 210: /* uniqueflag ::= */ {yymsp[1].minor.yy194 = OE_None;} break; - case 212: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 213: /* eidlist ::= eidlist COMMA nm collate sortorder */ { yymsp[-4].minor.yy148 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy148, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); } break; - case 213: /* eidlist ::= nm collate sortorder */ + case 214: /* eidlist ::= nm collate sortorder */ { yymsp[-2].minor.yy148 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy194, yymsp[0].minor.yy194); /*A-overwrites-Y*/ } break; - case 216: /* cmd ::= DROP INDEX ifexists fullname */ + case 217: /* cmd ::= DROP INDEX ifexists fullname */ {sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);} break; - case 217: /* cmd ::= VACUUM */ + case 218: /* cmd ::= VACUUM */ {sqlite3Vacuum(pParse,0);} break; - case 218: /* cmd ::= VACUUM nm */ + case 219: /* cmd ::= VACUUM nm */ {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} break; - case 219: /* cmd ::= PRAGMA nm dbnm */ + case 220: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 220: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 221: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 221: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 222: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 222: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 223: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 223: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 224: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 226: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 227: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy145, &all); } break; - case 227: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 228: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 228: /* trigger_time ::= BEFORE */ + case 229: /* trigger_time ::= BEFORE */ { yymsp[0].minor.yy194 = TK_BEFORE; } break; - case 229: /* trigger_time ::= AFTER */ + case 230: /* trigger_time ::= AFTER */ { yymsp[0].minor.yy194 = TK_AFTER; } break; - case 230: /* trigger_time ::= INSTEAD OF */ + case 231: /* trigger_time ::= INSTEAD OF */ { yymsp[-1].minor.yy194 = TK_INSTEAD;} break; - case 231: /* trigger_time ::= */ + case 232: /* trigger_time ::= */ { yymsp[1].minor.yy194 = TK_BEFORE; } break; - case 232: /* trigger_event ::= DELETE|INSERT */ - case 233: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==233); + case 233: /* trigger_event ::= DELETE|INSERT */ + case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); {yymsp[0].minor.yy332.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy332.b = 0;} break; - case 234: /* trigger_event ::= UPDATE OF idlist */ + case 235: /* trigger_event ::= UPDATE OF idlist */ {yymsp[-2].minor.yy332.a = TK_UPDATE; yymsp[-2].minor.yy332.b = yymsp[0].minor.yy254;} break; - case 235: /* when_clause ::= */ - case 254: /* key_opt ::= */ yytestcase(yyruleno==254); + case 236: /* when_clause ::= */ + case 255: /* key_opt ::= */ yytestcase(yyruleno==255); { yymsp[1].minor.yy72 = 0; } break; - case 236: /* when_clause ::= WHEN expr */ - case 255: /* key_opt ::= KEY expr */ yytestcase(yyruleno==255); + case 237: /* when_clause ::= WHEN expr */ + case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); { yymsp[-1].minor.yy72 = yymsp[0].minor.yy190.pExpr; } break; - case 237: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { assert( yymsp[-2].minor.yy145!=0 ); yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145; yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 238: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ { assert( yymsp[-1].minor.yy145!=0 ); yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145; } break; - case 239: /* trnm ::= nm DOT nm */ + case 240: /* 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 240: /* tridxby ::= INDEXED BY nm */ + case 241: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 241: /* tridxby ::= NOT INDEXED */ + case 242: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 242: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ + case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ {yymsp[-6].minor.yy145 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy194);} break; - case 243: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ + case 244: /* trigger_cmd ::= insert_cmd INTO trnm idlist_opt select */ {yymsp[-4].minor.yy145 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy243, yymsp[-4].minor.yy194);/*A-overwrites-R*/} break; - case 244: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ + case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ {yymsp[-4].minor.yy145 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);} break; - case 245: /* trigger_cmd ::= select */ + case 246: /* trigger_cmd ::= select */ {yymsp[0].minor.yy145 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); /*A-overwrites-X*/} break; - case 246: /* expr ::= RAISE LP IGNORE RP */ + case 247: /* expr ::= RAISE LP IGNORE RP */ { spanSet(&yymsp[-3].minor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + yymsp[-3].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); if( yymsp[-3].minor.yy190.pExpr ){ yymsp[-3].minor.yy190.pExpr->affinity = OE_Ignore; } } break; - case 247: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ { spanSet(&yymsp[-5].minor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/ - yymsp[-5].minor.yy190.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + yymsp[-5].minor.yy190.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); if( yymsp[-5].minor.yy190.pExpr ) { yymsp[-5].minor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194; } } break; - case 248: /* raisetype ::= ROLLBACK */ + case 249: /* raisetype ::= ROLLBACK */ {yymsp[0].minor.yy194 = OE_Rollback;} break; - case 250: /* raisetype ::= FAIL */ + case 251: /* raisetype ::= FAIL */ {yymsp[0].minor.yy194 = OE_Fail;} break; - case 251: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ { sqlite3DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194); } break; - case 252: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { sqlite3Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72); } break; - case 253: /* cmd ::= DETACH database_kw_opt expr */ + case 254: /* cmd ::= DETACH database_kw_opt expr */ { sqlite3Detach(pParse, yymsp[0].minor.yy190.pExpr); } break; - case 256: /* cmd ::= REINDEX */ + case 257: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 257: /* cmd ::= REINDEX nm dbnm */ + case 258: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 258: /* cmd ::= ANALYZE */ + case 259: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 259: /* cmd ::= ANALYZE nm dbnm */ + case 260: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 260: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0); } break; - case 261: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 262: /* add_column_fullname ::= fullname */ + case 263: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy185); } break; - case 263: /* cmd ::= create_vtab */ + case 264: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 264: /* cmd ::= create_vtab LP vtabarglist RP */ + case 265: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 265: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy194); } break; - case 266: /* vtabarg ::= */ + case 267: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 267: /* vtabargtoken ::= ANY */ - case 268: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==268); - case 269: /* lp ::= LP */ yytestcase(yyruleno==269); + case 268: /* vtabargtoken ::= ANY */ + case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); + case 270: /* lp ::= LP */ yytestcase(yyruleno==270); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 270: /* with ::= */ + case 271: /* with ::= */ {yymsp[1].minor.yy285 = 0;} break; - case 271: /* with ::= WITH wqlist */ + case 272: /* with ::= WITH wqlist */ { yymsp[-1].minor.yy285 = yymsp[0].minor.yy285; } break; - case 272: /* with ::= WITH RECURSIVE wqlist */ + case 273: /* with ::= WITH RECURSIVE wqlist */ { yymsp[-2].minor.yy285 = yymsp[0].minor.yy285; } break; - case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 274: /* wqlist ::= nm eidlist_opt AS LP select RP */ { yymsp[-5].minor.yy285 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); /*A-overwrites-X*/ } break; - case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 275: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { yymsp[-7].minor.yy285 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy285, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy148, yymsp[-1].minor.yy243); } break; default: - /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); - /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); - /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); - /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); - /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); - /* (280) explain ::= */ yytestcase(yyruleno==280); - /* (281) trans_opt ::= */ yytestcase(yyruleno==281); - /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); - /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); - /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); - /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); - /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); - /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); - /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); - /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); - /* (290) nm ::= STRING */ yytestcase(yyruleno==290); - /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); - /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); - /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); - /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); - /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); - /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); - /* (297) carglist ::= */ yytestcase(yyruleno==297); - /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); - /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); - /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); - /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); - /* (302) tconscomma ::= */ yytestcase(yyruleno==302); - /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); - /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); - /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); - /* (306) oneselect ::= values */ yytestcase(yyruleno==306); - /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); - /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); - /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); - /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310); + /* (276) input ::= cmdlist */ yytestcase(yyruleno==276); + /* (277) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==277); + /* (278) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=278); + /* (279) ecmd ::= SEMI */ yytestcase(yyruleno==279); + /* (280) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==280); + /* (281) explain ::= */ yytestcase(yyruleno==281); + /* (282) trans_opt ::= */ yytestcase(yyruleno==282); + /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283); + /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284); + /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285); + /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286); + /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287); + /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288); + /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289); + /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290); + /* (291) nm ::= STRING */ yytestcase(yyruleno==291); + /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292); + /* (293) typetoken ::= typename */ yytestcase(yyruleno==293); + /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294); + /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); + /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296); + /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297); + /* (298) carglist ::= */ yytestcase(yyruleno==298); + /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299); + /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300); + /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301); + /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302); + /* (303) tconscomma ::= */ yytestcase(yyruleno==303); + /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304); + /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305); + /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306); + /* (307) oneselect ::= values */ yytestcase(yyruleno==307); + /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308); + /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309); + /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310); /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); @@ -138690,17 +136627,17 @@ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ /* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27, /* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10, +/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 12, 17, 20, 10, /* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27, -/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6, +/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 7, /* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8, /* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, /* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, -/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, +/* 9x */ 25, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, /* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, /* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, /* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27, /* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27, /* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, @@ -139373,48 +137310,44 @@ ** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that ** error message. */ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ int nErr = 0; /* Number of errors encountered */ + int i; /* Loop counter */ void *pEngine; /* The LEMON-generated LALR(1) parser */ - int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ -#ifdef sqlite3Parser_ENGINEALWAYSONSTACK - unsigned char zSpace[sizeof(yyParser)]; /* Space for parser engine object */ -#endif assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->nVdbeActive==0 ){ db->u1.isInterrupted = 0; } pParse->rc = SQLITE_OK; pParse->zTail = zSql; + i = 0; assert( pzErrMsg!=0 ); /* sqlite3ParserTrace(stdout, "parser: "); */ -#ifdef sqlite3Parser_ENGINEALWAYSONSTACK - pEngine = zSpace; - sqlite3ParserInit(pEngine); -#else pEngine = sqlite3ParserAlloc(sqlite3Malloc); if( pEngine==0 ){ sqlite3OomFault(db); return SQLITE_NOMEM_BKPT; } -#endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); - assert( pParse->pVList==0 ); + assert( pParse->nzVar==0 ); + assert( pParse->azVar==0 ); while( 1 ){ - if( zSql[0]!=0 ){ - n = sqlite3GetToken((u8*)zSql, &tokenType); - mxSqlLen -= n; - if( mxSqlLen<0 ){ + assert( i>=0 ); + if( zSql[i]!=0 ){ + pParse->sLastToken.z = &zSql[i]; + pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType); + i += pParse->sLastToken.n; + if( i>mxSqlLen ){ pParse->rc = SQLITE_TOOBIG; break; } }else{ /* Upon reaching the end of input, call the parser two more times @@ -139424,46 +137357,38 @@ }else if( lastTokenParsed==0 ){ break; }else{ tokenType = TK_SEMI; } - zSql -= n; } if( tokenType>=TK_SPACE ){ assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); if( db->u1.isInterrupted ){ pParse->rc = SQLITE_INTERRUPT; break; } if( tokenType==TK_ILLEGAL ){ - sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); + sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", + &pParse->sLastToken); break; } - zSql += n; }else{ - pParse->sLastToken.z = zSql; - pParse->sLastToken.n = n; sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); lastTokenParsed = tokenType; - zSql += n; if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; } } assert( nErr==0 ); - pParse->zTail = zSql; + pParse->zTail = &zSql[i]; #ifdef YYTRACKMAXSTACKDEPTH sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); sqlite3_mutex_leave(sqlite3MallocMutex()); #endif /* YYDEBUG */ -#ifdef sqlite3Parser_ENGINEALWAYSONSTACK - sqlite3ParserFinalize(pEngine); -#else sqlite3ParserFree(pEngine, sqlite3_free); -#endif if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM_BKPT; } if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); @@ -139498,11 +137423,12 @@ sqlite3DeleteTable(db, pParse->pNewTable); } if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree); sqlite3DeleteTrigger(db, pParse->pNewTrigger); - sqlite3DbFree(db, pParse->pVList); + for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); + sqlite3DbFree(db, pParse->azVar); while( pParse->pAinc ){ AutoincInfo *p = pParse->pAinc; pParse->pAinc = p->pNext; sqlite3DbFree(db, p); } @@ -140711,11 +138637,10 @@ } aFlagOp[] = { { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, - { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ for(i=0; ilastRowid; } -/* -** Set the value returned by the sqlite3_last_insert_rowid() API function. -*/ -SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){ -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - (void)SQLITE_MISUSE_BKPT; - return; - } -#endif - sqlite3_mutex_enter(db->mutex); - db->lastRowid = iRowid; - sqlite3_mutex_leave(db->mutex); -} - /* ** Return the number of changes in the most recent call to sqlite3_exec(). */ SQLITE_API int sqlite3_changes(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR @@ -141484,11 +139394,11 @@ /* ** Cause any pending operation to stop at its earliest opportunity. */ SQLITE_API void sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){ + if( !sqlite3SafetyCheckOk(db) ){ (void)SQLITE_MISUSE_BKPT; return; } #endif db->u1.isInterrupted = 1; @@ -142023,17 +139933,10 @@ db->busyHandler.nBusy = 0; rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt); sqlite3Error(db, rc); } rc = sqlite3ApiExit(db, rc); - - /* If there are no active statements, clear the interrupt flag at this - ** point. */ - if( db->nVdbeActive==0 ){ - db->u1.isInterrupted = 0; - } - sqlite3_mutex_leave(db->mutex); return rc; #endif } @@ -142532,11 +140435,10 @@ int octet = (sqlite3HexToInt(zUri[iIn++]) << 4); octet += sqlite3HexToInt(zUri[iIn++]); assert( octet>=0 && octet<256 ); if( octet==0 ){ -#ifndef SQLITE_ENABLE_URI_00_ERROR /* This branch is taken when "%00" appears within the URI. In this ** case we ignore all text in the remainder of the path, name or ** value currently being parsed. So ignore the current character ** and skip to the next "?", "=" or "&", as appropriate. */ while( (c = zUri[iIn])!=0 && c!='#' @@ -142545,16 +140447,10 @@ && (eState!=2 || c!='&') ){ iIn++; } continue; -#else - /* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */ - *pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri"); - rc = SQLITE_ERROR; - goto parse_uri_out; -#endif } c = octet; }else if( eState==1 && (c=='&' || c=='=') ){ if( zFile[iOut-1]==0 ){ /* An empty option name. Ignore this option altogether. */ @@ -142655,13 +140551,11 @@ } }else{ zFile = sqlite3_malloc64(nUri+2); if( !zFile ) return SQLITE_NOMEM_BKPT; - if( nUri ){ - memcpy(zFile, zUri, nUri); - } + memcpy(zFile, zUri, nUri); zFile[nUri] = '\0'; zFile[nUri+1] = '\0'; flags &= ~SQLITE_OPEN_URI; } @@ -143451,11 +141345,11 @@ /* ** Interface to the testing logic. */ SQLITE_API int sqlite3_test_control(int op, ...){ int rc = 0; -#ifdef SQLITE_UNTESTABLE +#ifdef SQLITE_OMIT_BUILTIN_TEST UNUSED_PARAMETER(op); #else va_list ap; va_start(ap, op); switch( op ){ @@ -143788,11 +141682,11 @@ sqlite3_mutex_leave(db->mutex); break; } } va_end(ap); -#endif /* SQLITE_UNTESTABLE */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ return rc; } /* ** This is a utility routine, useful to VFS implementations, that checks @@ -143844,12 +141738,19 @@ /* ** Return the Btree pointer identified by zDbName. Return NULL if not found. */ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ - int iDb = zDbName ? sqlite3FindDbName(db, zDbName) : 0; - return iDb<0 ? 0 : db->aDb[iDb].pBt; + int i; + for(i=0; inDb; i++){ + if( db->aDb[i].pBt + && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zDbSName)==0) + ){ + return db->aDb[i].pBt; + } + } + return 0; } /* ** Return the filename of the database associated with a database ** connection. @@ -143892,27 +141793,26 @@ const char *zDb, sqlite3_snapshot **ppSnapshot ){ int rc = SQLITE_ERROR; #ifndef SQLITE_OMIT_WAL + int iDb; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ){ return SQLITE_MISUSE_BKPT; } #endif sqlite3_mutex_enter(db->mutex); - if( db->autoCommit==0 ){ - int iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( 0==sqlite3BtreeIsInTrans(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); - } + iDb = sqlite3FindDbName(db, zDb); + if( iDb==0 || iDb>1 ){ + Btree *pBt = db->aDb[iDb].pBt; + if( 0==sqlite3BtreeIsInTrans(pBt) ){ + rc = sqlite3BtreeBeginTrans(pBt, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot); } } } sqlite3_mutex_leave(db->mutex); @@ -143950,42 +141850,10 @@ } } } } - sqlite3_mutex_leave(db->mutex); -#endif /* SQLITE_OMIT_WAL */ - return rc; -} - -/* -** Recover as many snapshots as possible from the wal file associated with -** schema zDb of database db. -*/ -SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){ - int rc = SQLITE_ERROR; - int iDb; -#ifndef SQLITE_OMIT_WAL - -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ){ - return SQLITE_MISUSE_BKPT; - } -#endif - - sqlite3_mutex_enter(db->mutex); - iDb = sqlite3FindDbName(db, zDb); - if( iDb==0 || iDb>1 ){ - Btree *pBt = db->aDb[iDb].pBt; - if( 0==sqlite3BtreeIsInReadTrans(pBt) ){ - rc = sqlite3BtreeBeginTrans(pBt, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt)); - sqlite3BtreeCommit(pBt); - } - } - } sqlite3_mutex_leave(db->mutex); #endif /* SQLITE_OMIT_WAL */ return rc; } @@ -145137,11 +143005,10 @@ /* Precompiled statements used by the implementation. Each of these ** statements is run and reset within a single virtual table API call. */ sqlite3_stmt *aStmt[40]; - sqlite3_stmt *pSeekStmt; /* Cache for fts3CursorSeekStmt() */ char *zReadExprlist; char *zWriteExprlist; int nNodeSize; /* Soft limit for node size */ @@ -145207,11 +143074,10 @@ struct Fts3Cursor { sqlite3_vtab_cursor base; /* Base class used by SQLite core */ i16 eSearch; /* Search strategy (see below) */ u8 isEof; /* True if at End Of Results */ u8 isRequireSeek; /* True if must seek pStmt to %_content row */ - u8 bSeekStmt; /* True if pStmt is a seek */ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ Fts3Expr *pExpr; /* Parsed MATCH query string */ int iLangid; /* Language being queried for */ int nPhrase; /* Number of matchable phrases in query */ Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ @@ -145587,13 +143453,12 @@ /* ** Read a 64-bit variable-length integer from memory starting at p[0]. ** Return the number of bytes read, or 0 on error. ** The value is stored in *v. */ -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ - const unsigned char *p = (const unsigned char*)pBuf; - const unsigned char *pStart = p; +SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){ + const char *pStart = p; u32 a; u64 b; int shift; GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1); @@ -145731,11 +143596,10 @@ assert( p->nPendingData==0 ); assert( p->pSegments==0 ); /* Free any prepared statements held */ - sqlite3_finalize(p->pSeekStmt); for(i=0; iaStmt); i++){ sqlite3_finalize(p->aStmt[i]); } sqlite3_free(p->zSegmentsTbl); sqlite3_free(p->zReadExprlist); @@ -146603,13 +144467,13 @@ p->nPendingData = 0; p->azColumn = (char **)&p[1]; p->pTokenizer = pTokenizer; p->nMaxPendingData = FTS3_MAX_PENDING_DATA; p->bHasDocsize = (isFts4 && bNoDocsize==0); - p->bHasStat = (u8)isFts4; - p->bFts4 = (u8)isFts4; - p->bDescIdx = (u8)bDescIdx; + p->bHasStat = isFts4; + p->bFts4 = isFts4; + p->bDescIdx = bDescIdx; p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */ p->zContentTbl = zContent; p->zLanguageid = zLanguageid; zContent = 0; zLanguageid = 0; @@ -146636,13 +144500,11 @@ /* Fill in the azColumn array */ for(iCol=0; iCol0 ){ - memcpy(zCsr, z, n); - } + memcpy(zCsr, z, n); zCsr[n] = '\0'; sqlite3Fts3Dequote(zCsr); p->azColumn[iCol] = zCsr; zCsr += n+1; assert( zCsr <= &((char *)p)[nByte] ); @@ -146922,38 +144784,18 @@ } memset(pCsr, 0, sizeof(Fts3Cursor)); return SQLITE_OK; } -/* -** Finalize the statement handle at pCsr->pStmt. -** -** Or, if that statement handle is one created by fts3CursorSeekStmt(), -** and the Fts3Table.pSeekStmt slot is currently NULL, save the statement -** pointer there instead of finalizing it. -*/ -static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){ - if( pCsr->bSeekStmt ){ - Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; - if( p->pSeekStmt==0 ){ - p->pSeekStmt = pCsr->pStmt; - sqlite3_reset(pCsr->pStmt); - pCsr->pStmt = 0; - } - pCsr->bSeekStmt = 0; - } - sqlite3_finalize(pCsr->pStmt); -} - /* ** Close the cursor. For additional information see the documentation ** on the xClose method of the virtual table interface. */ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ Fts3Cursor *pCsr = (Fts3Cursor *)pCursor; assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); - fts3CursorFinalizeStmt(pCsr); + sqlite3_finalize(pCsr->pStmt); sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3Fts3FreeDeferredTokens(pCsr); sqlite3_free(pCsr->aDoclist); sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); @@ -146967,27 +144809,24 @@ ** ** "SELECT FROM %_content WHERE rowid = ?" ** ** (or the equivalent for a content=xxx table) and set pCsr->pStmt to ** it. If an error occurs, return an SQLite error code. +** +** Otherwise, set *ppStmt to point to pCsr->pStmt and return SQLITE_OK. */ -static int fts3CursorSeekStmt(Fts3Cursor *pCsr){ +static int fts3CursorSeekStmt(Fts3Cursor *pCsr, sqlite3_stmt **ppStmt){ int rc = SQLITE_OK; if( pCsr->pStmt==0 ){ Fts3Table *p = (Fts3Table *)pCsr->base.pVtab; char *zSql; - if( p->pSeekStmt ){ - pCsr->pStmt = p->pSeekStmt; - p->pSeekStmt = 0; - }else{ - zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); - if( !zSql ) return SQLITE_NOMEM; - rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); - sqlite3_free(zSql); - } - if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1; - } + zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist); + if( !zSql ) return SQLITE_NOMEM; + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); + sqlite3_free(zSql); + } + *ppStmt = pCsr->pStmt; return rc; } /* ** Position the pCsr->pStmt statement so that it is on the row @@ -146995,11 +144834,13 @@ ** SQLITE_OK on success. */ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){ int rc = SQLITE_OK; if( pCsr->isRequireSeek ){ - rc = fts3CursorSeekStmt(pCsr); + sqlite3_stmt *pStmt = 0; + + rc = fts3CursorSeekStmt(pCsr, &pStmt); if( rc==SQLITE_OK ){ sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId); pCsr->isRequireSeek = 0; if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){ return SQLITE_OK; @@ -148453,11 +146294,11 @@ if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++]; if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++]; assert( iIdx==nVal ); /* In case the cursor has been used before, clear it now. */ - fts3CursorFinalizeStmt(pCsr); + sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr->aDoclist); sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); sqlite3Fts3ExprFree(pCsr->pExpr); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); @@ -148521,11 +146362,11 @@ sqlite3_free(zSql); }else{ rc = SQLITE_NOMEM; } }else if( eSearch==FTS3_DOCID_SEARCH ){ - rc = fts3CursorSeekStmt(pCsr); + rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt); if( rc==SQLITE_OK ){ rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons); } } if( rc!=SQLITE_OK ) return rc; @@ -148649,14 +146490,12 @@ ** segments. */ const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ Fts3Table *p = (Fts3Table*)pVtab; - int rc; - i64 iLastRowid = sqlite3_last_insert_rowid(p->db); + int rc = sqlite3Fts3PendingTermsFlush(p); - rc = sqlite3Fts3PendingTermsFlush(p); if( rc==SQLITE_OK && p->nLeafAdd>(nMinMerge/16) && p->nAutoincrmerge && p->nAutoincrmerge!=0xff ){ int mxLevel = 0; /* Maximum relative level value in db */ @@ -148667,11 +146506,10 @@ A = p->nLeafAdd * mxLevel; A += (A/2); if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); } sqlite3Fts3SegmentsClose(p); - sqlite3_set_last_insert_rowid(p->db, iLastRowid); return rc; } /* ** If it is currently unknown whether or not the FTS table has an %_stat @@ -148688,11 +146526,11 @@ sqlite3_stmt *pStmt = 0; rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); if( rc==SQLITE_OK ){ int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW); rc = sqlite3_finalize(pStmt); - if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat; + if( rc==SQLITE_OK ) p->bHasStat = bHasStat; } sqlite3_free(zSql); }else{ rc = SQLITE_NOMEM; } @@ -160278,18 +158116,15 @@ /* ** Convert the text beginning at *pz into an integer and return ** its value. Advance *pz to point to the first character past ** the integer. -** -** This function used for parameters to merge= and incrmerge= -** commands. */ static int fts3Getint(const char **pz){ const char *z = *pz; int i = 0; - while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0'; + while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0'; *pz = z; return i; } /* @@ -162851,20 +160686,20 @@ const char *zIn, /* Array of characters to make exceptions */ int nIn /* Length of z in bytes */ ){ const unsigned char *z = (const unsigned char *)zIn; const unsigned char *zTerm = &z[nIn]; - unsigned int iCode; + int iCode; int nEntry = 0; assert( bAlnum==0 || bAlnum==1 ); while( znException; z = (const unsigned char *)zIn; while( zi; j--) aNew[j] = aNew[j-1]; - aNew[i] = (int)iCode; + aNew[i] = iCode; nNew++; } } p->aiException = aNew; p->nException = nNew; @@ -163033,11 +160868,11 @@ int *piEnd, /* OUT: Ending offset of token */ int *piPos /* OUT: Position integer of token */ ){ unicode_cursor *pCsr = (unicode_cursor *)pC; unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer); - unsigned int iCode = 0; + int iCode = 0; char *zOut; const unsigned char *z = &pCsr->aInput[pCsr->iOff]; const unsigned char *zStart = z; const unsigned char *zEnd; const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput]; @@ -163045,11 +160880,11 @@ /* Scan past any delimiter characters before the start of the next token. ** Return SQLITE_DONE early if this takes us all the way to the end of ** the input. */ while( z=zTerm ) return SQLITE_DONE; zOut = pCsr->zToken; @@ -163065,20 +160900,20 @@ pCsr->nAlloc += 64; } /* Write the folded case of the last character read to the output */ zEnd = z; - iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic); + iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic); if( iOut ){ WRITE_UTF8(zOut, iOut); } /* If the cursor is not at EOF, read the next character */ if( z>=zTerm ) break; READ_UTF8(z, zTerm, iCode); - }while( unicodeIsAlnum(p, (int)iCode) - || sqlite3FtsUnicodeIsdiacritic((int)iCode) + }while( unicodeIsAlnum(p, iCode) + || sqlite3FtsUnicodeIsdiacritic(iCode) ); /* Set the output variables and return. */ pCsr->iOff = (int)(z - pCsr->aInput); *paToken = pCsr->zToken; @@ -163238,13 +161073,13 @@ }; static const unsigned int aAscii[4] = { 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, }; - if( (unsigned int)c<128 ){ - return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 ); - }else if( (unsigned int)c<(1<<22) ){ + if( c<128 ){ + return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); + }else if( c<(1<<22) ){ unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; int iRes = 0; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; int iLo = 0; while( iHi>=iLo ){ @@ -163433,21 +161268,20 @@ 65514, 65521, 65527, 65528, 65529, }; int ret = c; + assert( c>=0 ); assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); if( c<128 ){ if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); }else if( c<65536 ){ - const struct TableEntry *p; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; int iLo = 0; int iRes = -1; - assert( c>aEntry[0].iCode ); while( iHi>=iLo ){ int iTest = (iHi + iLo) / 2; int cmp = (c - aEntry[iTest].iCode); if( cmp>=0 ){ iRes = iTest; @@ -163454,16 +161288,18 @@ iLo = iTest+1; }else{ iHi = iTest-1; } } + assert( iRes<0 || c>=aEntry[iRes].iCode ); - assert( iRes>=0 && c>=aEntry[iRes].iCode ); - p = &aEntry[iRes]; - if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ - ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; - assert( ret>0 ); + if( iRes>=0 ){ + const struct TableEntry *p = &aEntry[iRes]; + if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ + ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; + assert( ret>0 ); + } } if( bRemoveDiacritic ) ret = remove_diacritic(ret); } @@ -163546,11 +161382,10 @@ /* #include */ #ifndef SQLITE_AMALGAMATION #include "sqlite3rtree.h" typedef sqlite3_int64 i64; -typedef sqlite3_uint64 u64; typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; #endif @@ -163595,33 +161430,28 @@ struct Rtree { sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* Host database connection */ int iNodeSize; /* Size in bytes of each node in the node table */ u8 nDim; /* Number of dimensions */ - u8 nDim2; /* Twice the number of dimensions */ u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ u8 nBytesPerCell; /* Bytes consumed per cell */ - u8 inWrTrans; /* True if inside write transaction */ int iDepth; /* Current depth of the r-tree structure */ char *zDb; /* Name of database containing r-tree table */ char *zName; /* Name of r-tree table */ - u32 nBusy; /* Current number of users of this structure */ + int nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ - u32 nCursor; /* Number of open cursors */ /* List of nodes removed during a CondenseTree operation. List is ** linked together via the pointer normally used for hash chains - ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree ** headed by the node (leaf nodes have RtreeNode.iNode==0). */ RtreeNode *pDeleted; int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */ - /* Blob I/O on xxx_node */ - sqlite3_blob *pNodeBlob; - /* Statements to read/write/delete a record from xxx_node */ + sqlite3_stmt *pReadNode; sqlite3_stmt *pWriteNode; sqlite3_stmt *pDeleteNode; /* Statements to read/write/delete a record from xxx_rowid */ sqlite3_stmt *pReadRowid; @@ -163846,164 +161676,68 @@ #endif #ifndef MIN # define MIN(x,y) ((x) > (y) ? (y) : (x)) #endif -/* What version of GCC is being used. 0 means GCC is not being used . -** Note that the GCC_VERSION macro will also be set correctly when using -** clang, since clang works hard to be gcc compatible. So the gcc -** optimizations will also work when compiling with clang. -*/ -#ifndef GCC_VERSION -#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) -# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) -#else -# define GCC_VERSION 0 -#endif -#endif - -/* The testcase() macro should already be defined in the amalgamation. If -** it is not, make it a no-op. -*/ -#ifndef SQLITE_AMALGAMATION -# define testcase(X) -#endif - -/* -** Macros to determine whether the machine is big or little endian, -** and whether or not that determination is run-time or compile-time. -** -** For best performance, an attempt is made to guess at the byte-order -** using C-preprocessor macros. If that is unsuccessful, or if -** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined -** at run-time. -*/ -#ifndef SQLITE_BYTEORDER -#if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ - defined(__arm__) -# define SQLITE_BYTEORDER 1234 -#elif defined(sparc) || defined(__ppc__) -# define SQLITE_BYTEORDER 4321 -#else -# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ -#endif -#endif - - -/* What version of MSVC is being used. 0 means MSVC is not being used */ -#ifndef MSVC_VERSION -#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) -# define MSVC_VERSION _MSC_VER -#else -# define MSVC_VERSION 0 -#endif -#endif - /* ** Functions to deserialize a 16 bit integer, 32 bit real number and ** 64 bit integer. The deserialized value is returned. */ static int readInt16(u8 *p){ return (p[0]<<8) + p[1]; } static void readCoord(u8 *p, RtreeCoord *pCoord){ - assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */ -#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - pCoord->u = _byteswap_ulong(*(u32*)p); -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - pCoord->u = __builtin_bswap32(*(u32*)p); -#elif SQLITE_BYTEORDER==4321 - pCoord->u = *(u32*)p; -#else pCoord->u = ( (((u32)p[0]) << 24) + (((u32)p[1]) << 16) + (((u32)p[2]) << 8) + (((u32)p[3]) << 0) ); -#endif } static i64 readInt64(u8 *p){ -#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - u64 x; - memcpy(&x, p, 8); - return (i64)_byteswap_uint64(x); -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - u64 x; - memcpy(&x, p, 8); - return (i64)__builtin_bswap64(x); -#elif SQLITE_BYTEORDER==4321 - i64 x; - memcpy(&x, p, 8); - return x; -#else - return (i64)( - (((u64)p[0]) << 56) + - (((u64)p[1]) << 48) + - (((u64)p[2]) << 40) + - (((u64)p[3]) << 32) + - (((u64)p[4]) << 24) + - (((u64)p[5]) << 16) + - (((u64)p[6]) << 8) + - (((u64)p[7]) << 0) + return ( + (((i64)p[0]) << 56) + + (((i64)p[1]) << 48) + + (((i64)p[2]) << 40) + + (((i64)p[3]) << 32) + + (((i64)p[4]) << 24) + + (((i64)p[5]) << 16) + + (((i64)p[6]) << 8) + + (((i64)p[7]) << 0) ); -#endif } /* ** Functions to serialize a 16 bit integer, 32 bit real number and ** 64 bit integer. The value returned is the number of bytes written ** to the argument buffer (always 2, 4 and 8 respectively). */ -static void writeInt16(u8 *p, int i){ +static int writeInt16(u8 *p, int i){ p[0] = (i>> 8)&0xFF; p[1] = (i>> 0)&0xFF; + return 2; } static int writeCoord(u8 *p, RtreeCoord *pCoord){ u32 i; - assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */ assert( sizeof(RtreeCoord)==4 ); assert( sizeof(u32)==4 ); -#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - i = __builtin_bswap32(pCoord->u); - memcpy(p, &i, 4); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - i = _byteswap_ulong(pCoord->u); - memcpy(p, &i, 4); -#elif SQLITE_BYTEORDER==4321 - i = pCoord->u; - memcpy(p, &i, 4); -#else i = pCoord->u; p[0] = (i>>24)&0xFF; p[1] = (i>>16)&0xFF; p[2] = (i>> 8)&0xFF; p[3] = (i>> 0)&0xFF; -#endif return 4; } static int writeInt64(u8 *p, i64 i){ -#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 - i = (i64)__builtin_bswap64((u64)i); - memcpy(p, &i, 8); -#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 - i = (i64)_byteswap_uint64((u64)i); - memcpy(p, &i, 8); -#elif SQLITE_BYTEORDER==4321 - memcpy(p, &i, 8); -#else p[0] = (i>>56)&0xFF; p[1] = (i>>48)&0xFF; p[2] = (i>>40)&0xFF; p[3] = (i>>32)&0xFF; p[4] = (i>>24)&0xFF; p[5] = (i>>16)&0xFF; p[6] = (i>> 8)&0xFF; p[7] = (i>> 0)&0xFF; -#endif return 8; } /* ** Increment the reference count of node p. @@ -164082,32 +161816,22 @@ nodeReference(pParent); } return pNode; } -/* -** Clear the Rtree.pNodeBlob object -*/ -static void nodeBlobReset(Rtree *pRtree){ - if( pRtree->pNodeBlob && pRtree->inWrTrans==0 && pRtree->nCursor==0 ){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - sqlite3_blob_close(pBlob); - } -} - /* ** Obtain a reference to an r-tree node. */ static int nodeAcquire( Rtree *pRtree, /* R-tree structure */ i64 iNode, /* Node number to load */ RtreeNode *pParent, /* Either the parent node or NULL */ RtreeNode **ppNode /* OUT: Acquired node */ ){ - int rc = SQLITE_OK; - RtreeNode *pNode = 0; + int rc; + int rc2 = SQLITE_OK; + RtreeNode *pNode; /* Check if the requested node is already in the hash table. If so, ** increase its reference count and return it. */ if( (pNode = nodeHashLookup(pRtree, iNode)) ){ @@ -164119,49 +161843,32 @@ pNode->nRef++; *ppNode = pNode; return SQLITE_OK; } - if( pRtree->pNodeBlob ){ - sqlite3_blob *pBlob = pRtree->pNodeBlob; - pRtree->pNodeBlob = 0; - rc = sqlite3_blob_reopen(pBlob, iNode); - pRtree->pNodeBlob = pBlob; - if( rc ){ - nodeBlobReset(pRtree); - if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM; - } - } - if( pRtree->pNodeBlob==0 ){ - char *zTab = sqlite3_mprintf("%s_node", pRtree->zName); - if( zTab==0 ) return SQLITE_NOMEM; - rc = sqlite3_blob_open(pRtree->db, pRtree->zDb, zTab, "data", iNode, 0, - &pRtree->pNodeBlob); - sqlite3_free(zTab); - } - if( rc ){ - nodeBlobReset(pRtree); - *ppNode = 0; - /* If unable to open an sqlite3_blob on the desired row, that can only - ** be because the shadow tables hold erroneous data. */ - if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB; - }else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){ - pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize); - if( !pNode ){ - rc = SQLITE_NOMEM; - }else{ - pNode->pParent = pParent; - pNode->zData = (u8 *)&pNode[1]; - pNode->nRef = 1; - pNode->iNode = iNode; - pNode->isDirty = 0; - pNode->pNext = 0; - rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData, - pRtree->iNodeSize, 0); - nodeReference(pParent); - } - } + sqlite3_bind_int64(pRtree->pReadNode, 1, iNode); + rc = sqlite3_step(pRtree->pReadNode); + if( rc==SQLITE_ROW ){ + const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0); + if( pRtree->iNodeSize==sqlite3_column_bytes(pRtree->pReadNode, 0) ){ + pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize); + if( !pNode ){ + rc2 = SQLITE_NOMEM; + }else{ + pNode->pParent = pParent; + pNode->zData = (u8 *)&pNode[1]; + pNode->nRef = 1; + pNode->iNode = iNode; + pNode->isDirty = 0; + pNode->pNext = 0; + memcpy(pNode->zData, zBlob, pRtree->iNodeSize); + nodeReference(pParent); + } + } + } + rc = sqlite3_reset(pRtree->pReadNode); + if( rc==SQLITE_OK ) rc = rc2; /* If the root node was just loaded, set pRtree->iDepth to the height ** of the r-tree structure. A height of zero means all data is stored on ** the root node. A height of one means the children of the root node ** are the leaves, and so on. If the depth as specified on the root node @@ -164209,11 +161916,11 @@ int iCell /* Index into pNode into which pCell is written */ ){ int ii; u8 *p = &pNode->zData[4 + pRtree->nBytesPerCell*iCell]; p += writeInt64(p, pCell->iRowid); - for(ii=0; iinDim2; ii++){ + for(ii=0; ii<(pRtree->nDim*2); ii++){ p += writeCoord(p, &pCell->aCoord[ii]); } pNode->isDirty = 1; } @@ -164343,20 +162050,17 @@ int iCell, /* Index of the cell within the node */ RtreeCell *pCell /* OUT: Write the cell contents here */ ){ u8 *pData; RtreeCoord *pCoord; - int ii = 0; + int ii; pCell->iRowid = nodeGetRowid(pRtree, pNode, iCell); pData = pNode->zData + (12 + pRtree->nBytesPerCell*iCell); pCoord = pCell->aCoord; - do{ - readCoord(pData, &pCoord[ii]); - readCoord(pData+4, &pCoord[ii+1]); - pData += 8; - ii += 2; - }while( iinDim2 ); + for(ii=0; iinDim*2; ii++){ + readCoord(&pData[ii*4], &pCoord[ii]); + } } /* Forward declaration for the function that does the work of ** the virtual table module xCreate() and xConnect() methods. @@ -164403,13 +162107,11 @@ ** zero the structure is deleted. */ static void rtreeRelease(Rtree *pRtree){ pRtree->nBusy--; if( pRtree->nBusy==0 ){ - pRtree->inWrTrans = 0; - pRtree->nCursor = 0; - nodeBlobReset(pRtree); + sqlite3_finalize(pRtree->pReadNode); sqlite3_finalize(pRtree->pWriteNode); sqlite3_finalize(pRtree->pDeleteNode); sqlite3_finalize(pRtree->pReadRowid); sqlite3_finalize(pRtree->pWriteRowid); sqlite3_finalize(pRtree->pDeleteRowid); @@ -164443,11 +162145,10 @@ pRtree->zDb, pRtree->zName ); if( !zCreate ){ rc = SQLITE_NOMEM; }else{ - nodeBlobReset(pRtree); rc = sqlite3_exec(pRtree->db, zCreate, 0, 0, 0); sqlite3_free(zCreate); } if( rc==SQLITE_OK ){ rtreeRelease(pRtree); @@ -164459,19 +162160,17 @@ /* ** Rtree virtual table module xOpen method. */ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ int rc = SQLITE_NOMEM; - Rtree *pRtree = (Rtree *)pVTab; RtreeCursor *pCsr; pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor)); if( pCsr ){ memset(pCsr, 0, sizeof(RtreeCursor)); pCsr->base.pVtab = pVTab; rc = SQLITE_OK; - pRtree->nCursor++; } *ppCursor = (sqlite3_vtab_cursor *)pCsr; return rc; } @@ -164500,17 +162199,14 @@ */ static int rtreeClose(sqlite3_vtab_cursor *cur){ Rtree *pRtree = (Rtree *)(cur->pVtab); int ii; RtreeCursor *pCsr = (RtreeCursor *)cur; - assert( pRtree->nCursor>0 ); freeCursorConstraints(pCsr); sqlite3_free(pCsr->aPoint); for(ii=0; iiaNode[ii]); sqlite3_free(pCsr); - pRtree->nCursor--; - nodeBlobReset(pRtree); return SQLITE_OK; } /* ** Rtree virtual table module xEof method. @@ -164529,34 +162225,27 @@ ** endian platforms. The on-disk record stores integer coordinates if ** eInt is true and it stores 32-bit floating point records if eInt is ** false. a[] is the four bytes of the on-disk record to be decoded. ** Store the results in "r". ** -** There are five versions of this macro. The last one is generic. The -** other four are various architectures-specific optimizations. +** There are three versions of this macro, one each for little-endian and +** big-endian processors and a third generic implementation. The endian- +** specific implementations are much faster and are preferred if the +** processor endianness is known at compile-time. The SQLITE_BYTEORDER +** macro is part of sqliteInt.h and hence the endian-specific +** implementation will only be used if this module is compiled as part +** of the amalgamation. */ -#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - c.u = _byteswap_ulong(*(u32*)a); \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 -#define RTREE_DECODE_COORD(eInt, a, r) { \ - RtreeCoord c; /* Coordinate decoded */ \ - c.u = __builtin_bswap32(*(u32*)a); \ - r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ -} -#elif SQLITE_BYTEORDER==1234 +#if defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==1234 #define RTREE_DECODE_COORD(eInt, a, r) { \ RtreeCoord c; /* Coordinate decoded */ \ memcpy(&c.u,a,4); \ c.u = ((c.u>>24)&0xff)|((c.u>>8)&0xff00)| \ ((c.u&0xff)<<24)|((c.u&0xff00)<<8); \ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } -#elif SQLITE_BYTEORDER==4321 +#elif defined(SQLITE_BYTEORDER) && SQLITE_BYTEORDER==4321 #define RTREE_DECODE_COORD(eInt, a, r) { \ RtreeCoord c; /* Coordinate decoded */ \ memcpy(&c.u,a,4); \ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } @@ -164579,58 +162268,30 @@ u8 *pCellData, /* Raw cell content */ RtreeSearchPoint *pSearch, /* Container of this cell */ sqlite3_rtree_dbl *prScore, /* OUT: score for the cell */ int *peWithin /* OUT: visibility of the cell */ ){ + int i; /* Loop counter */ sqlite3_rtree_query_info *pInfo = pConstraint->pInfo; /* Callback info */ int nCoord = pInfo->nCoord; /* No. of coordinates */ int rc; /* Callback return code */ - RtreeCoord c; /* Translator union */ sqlite3_rtree_dbl aCoord[RTREE_MAX_DIMENSIONS*2]; /* Decoded coordinates */ assert( pConstraint->op==RTREE_MATCH || pConstraint->op==RTREE_QUERY ); assert( nCoord==2 || nCoord==4 || nCoord==6 || nCoord==8 || nCoord==10 ); if( pConstraint->op==RTREE_QUERY && pSearch->iLevel==1 ){ pInfo->iRowid = readInt64(pCellData); } pCellData += 8; -#ifndef SQLITE_RTREE_INT_ONLY - if( eInt==0 ){ - switch( nCoord ){ - case 10: readCoord(pCellData+36, &c); aCoord[9] = c.f; - readCoord(pCellData+32, &c); aCoord[8] = c.f; - case 8: readCoord(pCellData+28, &c); aCoord[7] = c.f; - readCoord(pCellData+24, &c); aCoord[6] = c.f; - case 6: readCoord(pCellData+20, &c); aCoord[5] = c.f; - readCoord(pCellData+16, &c); aCoord[4] = c.f; - case 4: readCoord(pCellData+12, &c); aCoord[3] = c.f; - readCoord(pCellData+8, &c); aCoord[2] = c.f; - default: readCoord(pCellData+4, &c); aCoord[1] = c.f; - readCoord(pCellData, &c); aCoord[0] = c.f; - } - }else -#endif - { - switch( nCoord ){ - case 10: readCoord(pCellData+36, &c); aCoord[9] = c.i; - readCoord(pCellData+32, &c); aCoord[8] = c.i; - case 8: readCoord(pCellData+28, &c); aCoord[7] = c.i; - readCoord(pCellData+24, &c); aCoord[6] = c.i; - case 6: readCoord(pCellData+20, &c); aCoord[5] = c.i; - readCoord(pCellData+16, &c); aCoord[4] = c.i; - case 4: readCoord(pCellData+12, &c); aCoord[3] = c.i; - readCoord(pCellData+8, &c); aCoord[2] = c.i; - default: readCoord(pCellData+4, &c); aCoord[1] = c.i; - readCoord(pCellData, &c); aCoord[0] = c.i; - } + for(i=0; iop==RTREE_MATCH ){ - int eWithin = 0; rc = pConstraint->u.xGeom((sqlite3_rtree_geometry*)pInfo, - nCoord, aCoord, &eWithin); - if( eWithin==0 ) *peWithin = NOT_WITHIN; + nCoord, aCoord, &i); + if( i==0 ) *peWithin = NOT_WITHIN; *prScore = RTREE_ZERO; }else{ pInfo->aCoord = aCoord; pInfo->iLevel = pSearch->iLevel - 1; pInfo->rScore = pInfo->rParentScore = pSearch->rScore; @@ -164662,11 +162323,10 @@ */ pCellData += 8 + 4*(p->iCoord&0xfe); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ ); - assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */ switch( p->op ){ case RTREE_LE: case RTREE_LT: case RTREE_EQ: RTREE_DECODE_COORD(eInt, pCellData, val); @@ -164703,11 +162363,10 @@ RtreeDValue xN; /* Coordinate value converted to a double */ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ ); pCellData += 8 + p->iCoord*4; - assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */ RTREE_DECODE_COORD(eInt, pCellData, xN); switch( p->op ){ case RTREE_LE: if( xN <= p->u.rValue ) return; break; case RTREE_LT: if( xN < p->u.rValue ) return; break; case RTREE_GE: if( xN >= p->u.rValue ) return; break; @@ -164772,11 +162431,11 @@ if( pA->iLevel>pB->iLevel ) return +1; return 0; } /* -** Interchange two search points in a cursor. +** Interchange to search points in a cursor. */ static void rtreeSearchPointSwap(RtreeCursor *p, int i, int j){ RtreeSearchPoint t = p->aPoint[i]; assert( iaPoint[i] = p->aPoint[j]; @@ -165020,11 +162679,11 @@ rtreeSearchPointPop(pCur); } if( rScoreeWithin = (u8)eWithin; + p->eWithin = eWithin; p->id = x.id; p->iCell = x.iCell; RTREE_QUEUE_TRACE(pCur, "PUSH-S:"); break; } @@ -165079,10 +162738,11 @@ if( rc ) return rc; if( p==0 ) return SQLITE_OK; if( i==0 ){ sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell)); }else{ + if( rc ) return rc; nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); }else @@ -165207,11 +162867,11 @@ assert( p!=0 ); /* Always returns pCsr->sPoint */ pCsr->aNode[0] = pLeaf; p->id = iNode; p->eWithin = PARTLY_WITHIN; rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); - p->iCell = (u8)iCell; + p->iCell = iCell; RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); }else{ pCsr->atEOF = 1; } }else{ @@ -165240,11 +162900,11 @@ */ rc = deserializeGeometry(argv[ii], p); if( rc!=SQLITE_OK ){ break; } - p->pInfo->nCoord = pRtree->nDim2; + p->pInfo->nCoord = pRtree->nDim*2; p->pInfo->anQueue = pCsr->anQueue; p->pInfo->mxLevel = pRtree->iDepth + 1; }else{ #ifdef SQLITE_RTREE_INT_ONLY p->u.rValue = sqlite3_value_int64(argv[ii]); @@ -165255,11 +162915,11 @@ } } } if( rc==SQLITE_OK ){ RtreeSearchPoint *pNew; - pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); + pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, pRtree->iDepth+1); if( pNew==0 ) return SQLITE_NOMEM; pNew->id = 1; pNew->iCell = 0; pNew->eWithin = PARTLY_WITHIN; assert( pCsr->bPoint==1 ); @@ -165272,10 +162932,23 @@ nodeRelease(pRtree, pRoot); rtreeRelease(pRtree); return rc; } + +/* +** Set the pIdxInfo->estimatedRows variable to nRow. Unless this +** extension is currently being used by a version of SQLite too old to +** support estimatedRows. In that case this function is a no-op. +*/ +static void setEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ +#if SQLITE_VERSION_NUMBER>=3008002 + if( sqlite3_libversion_number()>=3008002 ){ + pIdxInfo->estimatedRows = nRow; + } +#endif +} /* ** Rtree virtual table module xBestIndex method. There are three ** table scan strategies to choose from (in order from most to ** least desirable): @@ -165352,11 +163025,11 @@ ** considered almost as quick as a direct rowid lookup (for which ** sqlite uses an internal cost of 0.0). It is expected to return ** a single row. */ pIdxInfo->estimatedCost = 30.0; - pIdxInfo->estimatedRows = 1; + setEstimatedRows(pIdxInfo, 1); return SQLITE_OK; } if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){ u8 op; @@ -165370,11 +163043,11 @@ assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH ); op = RTREE_MATCH; break; } zIdxStr[iIdx++] = op; - zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0'); + zIdxStr[iIdx++] = p->iColumn - 1 + '0'; pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2); pIdxInfo->aConstraintUsage[ii].omit = 1; } } @@ -165384,75 +163057,55 @@ return SQLITE_NOMEM; } nRow = pRtree->nRowEst >> (iIdx/2); pIdxInfo->estimatedCost = (double)6.0 * (double)nRow; - pIdxInfo->estimatedRows = nRow; + setEstimatedRows(pIdxInfo, nRow); return rc; } /* ** Return the N-dimensional volumn of the cell stored in *p. */ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ RtreeDValue area = (RtreeDValue)1; - assert( pRtree->nDim>=1 && pRtree->nDim<=5 ); -#ifndef SQLITE_RTREE_INT_ONLY - if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - switch( pRtree->nDim ){ - case 5: area = p->aCoord[9].f - p->aCoord[8].f; - case 4: area *= p->aCoord[7].f - p->aCoord[6].f; - case 3: area *= p->aCoord[5].f - p->aCoord[4].f; - case 2: area *= p->aCoord[3].f - p->aCoord[2].f; - default: area *= p->aCoord[1].f - p->aCoord[0].f; - } - }else -#endif - { - switch( pRtree->nDim ){ - case 5: area = p->aCoord[9].i - p->aCoord[8].i; - case 4: area *= p->aCoord[7].i - p->aCoord[6].i; - case 3: area *= p->aCoord[5].i - p->aCoord[4].i; - case 2: area *= p->aCoord[3].i - p->aCoord[2].i; - default: area *= p->aCoord[1].i - p->aCoord[0].i; - } + int ii; + for(ii=0; ii<(pRtree->nDim*2); ii+=2){ + area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); } return area; } /* ** Return the margin length of cell p. The margin length is the sum ** of the objects size in each dimension. */ static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ - RtreeDValue margin = 0; - int ii = pRtree->nDim2 - 2; - do{ + RtreeDValue margin = (RtreeDValue)0; + int ii; + for(ii=0; ii<(pRtree->nDim*2); ii+=2){ margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); - ii -= 2; - }while( ii>=0 ); + } return margin; } /* ** Store the union of cells p1 and p2 in p1. */ static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ - int ii = 0; + int ii; if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - do{ + for(ii=0; ii<(pRtree->nDim*2); ii+=2){ p1->aCoord[ii].f = MIN(p1->aCoord[ii].f, p2->aCoord[ii].f); p1->aCoord[ii+1].f = MAX(p1->aCoord[ii+1].f, p2->aCoord[ii+1].f); - ii += 2; - }while( iinDim2 ); + } }else{ - do{ + for(ii=0; ii<(pRtree->nDim*2); ii+=2){ p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i); p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i); - ii += 2; - }while( iinDim2 ); + } } } /* ** Return true if the area covered by p2 is a subset of the area covered @@ -165459,11 +163112,11 @@ ** by p1. False otherwise. */ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ int ii; int isInt = (pRtree->eCoordType==RTREE_COORD_INT32); - for(ii=0; iinDim2; ii+=2){ + for(ii=0; ii<(pRtree->nDim*2); ii+=2){ RtreeCoord *a1 = &p1->aCoord[ii]; RtreeCoord *a2 = &p2->aCoord[ii]; if( (!isInt && (a2[0].fa1[1].f)) || ( isInt && (a2[0].ia1[1].i)) ){ @@ -165494,11 +163147,11 @@ int ii; RtreeDValue overlap = RTREE_ZERO; for(ii=0; iinDim2; jj+=2){ + for(jj=0; jj<(pRtree->nDim*2); jj+=2){ RtreeDValue x1, x2; x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); if( x25)); ** This problem was discovered after years of use, so we silently ignore ** these kinds of misdeclared tables to avoid breaking any legacy. */ - assert( nData<=(pRtree->nDim2 + 3) ); + assert( nData<=(pRtree->nDim*2 + 3) ); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ for(ii=0; iiinWrTrans==0 ); - pRtree->inWrTrans++; - return SQLITE_OK; -} - -/* -** Called when a transaction completes (either by COMMIT or ROLLBACK). -** The sqlite3_blob object should be released at this point. -*/ -static int rtreeEndTransaction(sqlite3_vtab *pVtab){ - Rtree *pRtree = (Rtree *)pVtab; - pRtree->inWrTrans = 0; - nodeBlobReset(pRtree); - return SQLITE_OK; -} - /* ** The xRename method for rtree module virtual tables. */ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){ Rtree *pRtree = (Rtree *)pVtab; @@ -166681,11 +164313,10 @@ rc = sqlite3_exec(pRtree->db, zSql, 0, 0, 0); sqlite3_free(zSql); } return rc; } - /* ** This function populates the pRtree->nRowEst variable with an estimate ** of the number of rows in the virtual table. If possible, this is based ** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST. @@ -166742,19 +164373,19 @@ rtreeNext, /* xNext - advance a cursor */ rtreeEof, /* xEof */ rtreeColumn, /* xColumn - read data */ rtreeRowid, /* xRowid - read data */ rtreeUpdate, /* xUpdate - write data */ - rtreeBeginTransaction, /* xBegin - begin transaction */ - rtreeEndTransaction, /* xSync - sync transaction */ - rtreeEndTransaction, /* xCommit - commit transaction */ - rtreeEndTransaction, /* xRollback - rollback transaction */ + 0, /* xBegin - begin transaction */ + 0, /* xSync - sync transaction */ + 0, /* xCommit - commit transaction */ + 0, /* xRollback - rollback transaction */ 0, /* xFindFunction - function overloading */ rtreeRename, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ - 0, /* xRollbackTo */ + 0 /* xRollbackTo */ }; static int rtreeSqlInit( Rtree *pRtree, sqlite3 *db, @@ -166762,13 +164393,14 @@ const char *zPrefix, int isCreate ){ int rc = SQLITE_OK; - #define N_STATEMENT 8 + #define N_STATEMENT 9 static const char *azSql[N_STATEMENT] = { - /* Write the xxx_node table */ + /* Read and write the xxx_node table */ + "SELECT data FROM '%q'.'%q_node' WHERE nodeno = :1", "INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)", "DELETE FROM '%q'.'%q_node' WHERE nodeno = :1", /* Read and write the xxx_rowid table */ "SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1", @@ -166802,18 +164434,19 @@ if( rc!=SQLITE_OK ){ return rc; } } - appStmt[0] = &pRtree->pWriteNode; - appStmt[1] = &pRtree->pDeleteNode; - appStmt[2] = &pRtree->pReadRowid; - appStmt[3] = &pRtree->pWriteRowid; - appStmt[4] = &pRtree->pDeleteRowid; - appStmt[5] = &pRtree->pReadParent; - appStmt[6] = &pRtree->pWriteParent; - appStmt[7] = &pRtree->pDeleteParent; + appStmt[0] = &pRtree->pReadNode; + appStmt[1] = &pRtree->pWriteNode; + appStmt[2] = &pRtree->pDeleteNode; + appStmt[3] = &pRtree->pReadRowid; + appStmt[4] = &pRtree->pWriteRowid; + appStmt[5] = &pRtree->pDeleteRowid; + appStmt[6] = &pRtree->pReadParent; + appStmt[7] = &pRtree->pWriteParent; + appStmt[8] = &pRtree->pDeleteParent; rc = rtreeQueryStat1(db, pRtree); for(i=0; inBusy = 1; pRtree->base.pModule = &rtreeModule; pRtree->zDb = (char *)&pRtree[1]; pRtree->zName = &pRtree->zDb[nDb+1]; - pRtree->nDim = (u8)((argc-4)/2); - pRtree->nDim2 = pRtree->nDim*2; - pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; - pRtree->eCoordType = (u8)eCoordType; + pRtree->nDim = (argc-4)/2; + pRtree->nBytesPerCell = 8 + pRtree->nDim*4*2; + pRtree->eCoordType = eCoordType; memcpy(pRtree->zDb, argv[1], nDb); memcpy(pRtree->zName, argv[2], nName); /* Figure out the node size to use. */ rc = getNodeSize(db, pRtree, isCreate, pzErr); @@ -167023,12 +164655,11 @@ int ii; UNUSED_PARAMETER(nArg); memset(&node, 0, sizeof(RtreeNode)); memset(&tree, 0, sizeof(Rtree)); - tree.nDim = (u8)sqlite3_value_int(apArg[0]); - tree.nDim2 = tree.nDim*2; + tree.nDim = sqlite3_value_int(apArg[0]); tree.nBytesPerCell = 8 + 8 * tree.nDim; node.zData = (u8 *)sqlite3_value_blob(apArg[1]); for(ii=0; iizName, p->nArg, p->enc, - p->iContext ? (void*)db : (void*)0, - p->xFunc, 0, 0 + db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0 ); } return rc; } @@ -169005,11 +166638,10 @@ int nStep; /* Rows processed for current object */ int nProgress; /* Rows processed for all objects */ RbuObjIter objiter; /* Iterator for skipping through tbl/idx */ const char *zVfsName; /* Name of automatically created rbu vfs */ rbu_file *pTargetFd; /* File handle open on target db */ - int nPagePerSector; /* Pages per sector for pTargetFd */ i64 iOalSz; i64 nPhaseOneStep; /* The following state variables are used as part of the incremental ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding @@ -170983,11 +168615,11 @@ /* ** Open the database handle and attach the RBU database as "rbu". If an ** error occurs, leave an error code and message in the RBU handle. */ -static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){ +static void rbuOpenDatabase(sqlite3rbu *p){ assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); /* Open the RBU database */ p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); @@ -171058,11 +168690,11 @@ if( p->eStage>=RBU_STAGE_MOVE ){ bOpen = 1; }else{ RbuState *pState = rbuLoadState(p); if( pState ){ - bOpen = (pState->eStage>=RBU_STAGE_MOVE); + bOpen = (pState->eStage>RBU_STAGE_MOVE); rbuFreeState(pState); } } if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1); } @@ -171070,19 +168702,10 @@ p->eStage = 0; if( p->rc==SQLITE_OK && p->dbMain==0 ){ if( !rbuIsVacuum(p) ){ p->dbMain = rbuOpenDbhandle(p, p->zTarget, 1); }else if( p->pRbuFd->pWalFd ){ - if( pbRetry ){ - p->pRbuFd->bNolock = 0; - sqlite3_close(p->dbRbu); - sqlite3_close(p->dbMain); - p->dbMain = 0; - p->dbRbu = 0; - *pbRetry = 1; - return; - } p->rc = SQLITE_ERROR; p->zErrmsg = sqlite3_mprintf("cannot vacuum wal mode database"); }else{ char *zTarget; char *zExtra = 0; @@ -171259,39 +168882,20 @@ p->eStage = RBU_STAGE_CAPTURE; rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0); if( rc2!=SQLITE_INTERNAL ) p->rc = rc2; } - if( p->rc==SQLITE_OK && p->nFrame>0 ){ + if( p->rc==SQLITE_OK ){ p->eStage = RBU_STAGE_CKPT; p->nStep = (pState ? pState->nRow : 0); p->aBuf = rbuMalloc(p, p->pgsz); p->iWalCksum = rbuShmChecksum(p); } - if( p->rc==SQLITE_OK ){ - if( p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum) ){ - p->rc = SQLITE_DONE; - p->eStage = RBU_STAGE_DONE; - }else{ - int nSectorSize; - sqlite3_file *pDb = p->pTargetFd->pReal; - sqlite3_file *pWal = p->pTargetFd->pWalFd->pReal; - assert( p->nPagePerSector==0 ); - nSectorSize = pDb->pMethods->xSectorSize(pDb); - if( nSectorSize>p->pgsz ){ - p->nPagePerSector = nSectorSize / p->pgsz; - }else{ - p->nPagePerSector = 1; - } - - /* Call xSync() on the wal file. This causes SQLite to sync the - ** directory in which the target database and the wal file reside, in - ** case it has not been synced since the rename() call in - ** rbuMoveOalFile(). */ - p->rc = pWal->pMethods->xSync(pWal, SQLITE_SYNC_NORMAL); - } + if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){ + p->rc = SQLITE_DONE; + p->eStage = RBU_STAGE_DONE; } } /* ** Called when iAmt bytes are read from offset iOff of the wal file while @@ -171460,11 +169064,11 @@ #else p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK; #endif if( p->rc==SQLITE_OK ){ - rbuOpenDatabase(p, 0); + rbuOpenDatabase(p); rbuSetupCheckpoint(p, 0); } } } @@ -171942,30 +169546,13 @@ if( p->rc==SQLITE_OK ){ p->eStage = RBU_STAGE_DONE; p->rc = SQLITE_DONE; } }else{ - /* At one point the following block copied a single frame from the - ** wal file to the database file. So that one call to sqlite3rbu_step() - ** checkpointed a single frame. - ** - ** However, if the sector-size is larger than the page-size, and the - ** application calls sqlite3rbu_savestate() or close() immediately - ** after this step, then rbu_step() again, then a power failure occurs, - ** then the database page written here may be damaged. Work around - ** this by checkpointing frames until the next page in the aFrame[] - ** lies on a different disk sector to the current one. */ - u32 iSector; - do{ - RbuFrame *pFrame = &p->aFrame[p->nStep]; - iSector = (pFrame->iDbPage-1) / p->nPagePerSector; - rbuCheckpointFrame(p, pFrame); - p->nStep++; - }while( p->nStepnFrame - && iSector==((p->aFrame[p->nStep].iDbPage-1) / p->nPagePerSector) - && p->rc==SQLITE_OK - ); + RbuFrame *pFrame = &p->aFrame[p->nStep]; + rbuCheckpointFrame(p, pFrame); + p->nStep++; } p->nProgress++; } break; } @@ -172188,11 +169775,10 @@ rbuCreateVfs(p); /* Open the target, RBU and state databases */ if( p->rc==SQLITE_OK ){ char *pCsr = (char*)&p[1]; - int bRetry = 0; if( zTarget ){ p->zTarget = pCsr; memcpy(p->zTarget, zTarget, nTarget+1); pCsr += nTarget+1; } @@ -172200,22 +169786,11 @@ memcpy(p->zRbu, zRbu, nRbu+1); pCsr += nRbu+1; if( zState ){ p->zState = rbuMPrintf(p, "%s", zState); } - - /* If the first attempt to open the database file fails and the bRetry - ** flag it set, this means that the db was not opened because it seemed - ** to be a wal-mode db. But, this may have happened due to an earlier - ** RBU vacuum operation leaving an old wal file in the directory. - ** If this is the case, it will have been checkpointed and deleted - ** when the handle was closed and a second attempt to open the - ** database may succeed. */ - rbuOpenDatabase(p, &bRetry); - if( bRetry ){ - rbuOpenDatabase(p, 0); - } + rbuOpenDatabase(p); } if( p->rc==SQLITE_OK ){ pState = rbuLoadState(p); assert( pState || p->rc!=SQLITE_OK ); @@ -172402,16 +169977,10 @@ /* Commit the transaction to the *-oal file. */ if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ p->rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, &p->zErrmsg); } - /* Sync the db file if currently doing an incremental checkpoint */ - if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){ - sqlite3_file *pDb = p->pTargetFd->pReal; - p->rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); - } - rbuSaveState(p, p->eStage); if( p->rc==SQLITE_OK && p->eStage==RBU_STAGE_OAL ){ p->rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, &p->zErrmsg); } @@ -172532,16 +170101,10 @@ if( p->eStage==RBU_STAGE_OAL ){ assert( rc!=SQLITE_DONE ); if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "COMMIT", 0, 0, 0); } - /* Sync the db file */ - if( rc==SQLITE_OK && p->eStage==RBU_STAGE_CKPT ){ - sqlite3_file *pDb = p->pTargetFd->pReal; - rc = pDb->pMethods->xSync(pDb, SQLITE_SYNC_NORMAL); - } - p->rc = rc; rbuSaveState(p, p->eStage); rc = p->rc; if( p->eStage==RBU_STAGE_OAL ){ @@ -174532,11 +172095,13 @@ if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; nVarint = sessionVarintLen(n); if( aBuf ){ sessionVarintPut(&aBuf[1], n); - if( n ) memcpy(&aBuf[nVarint + 1], z, n); + memcpy(&aBuf[nVarint + 1], eType==SQLITE_TEXT ? + sqlite3_value_text(pValue) : sqlite3_value_blob(pValue), n + ); } nByte = 1 + nVarint + n; break; } @@ -175948,11 +173513,11 @@ SessionBuffer *p, const u8 *aBlob, int nBlob, int *pRc ){ - if( nBlob>0 && 0==sessionBufferGrow(p, nBlob, pRc) ){ + if( 0==sessionBufferGrow(p, nBlob, pRc) ){ memcpy(&p->aBuf[p->nBuf], aBlob, nBlob); p->nBuf += nBlob; } } @@ -176134,17 +173699,17 @@ bChanged = 1; break; } default: { - int n; - int nHdr = 1 + sessionVarintGet(&pCsr[1], &n); + int nByte; + int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte); assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); - nAdvance = nHdr + n; + nAdvance = nHdr + nByte; if( eType==sqlite3_column_type(pStmt, i) - && n==sqlite3_column_bytes(pStmt, i) - && (n==0 || 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), n)) + && nByte==sqlite3_column_bytes(pStmt, i) + && 0==memcmp(&pCsr[nHdr], sqlite3_column_blob(pStmt, i), nByte) ){ break; } bChanged = 1; } @@ -177186,11 +174751,11 @@ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ){ if( !pIter->pConflict ){ return SQLITE_MISUSE; } - if( iVal<0 || iVal>=pIter->nCol ){ + if( iVal<0 || iVal>=sqlite3_column_count(pIter->pConflict) ){ return SQLITE_RANGE; } *ppValue = sqlite3_column_value(pIter->pConflict, iVal); return SQLITE_OK; } @@ -177653,17 +175218,11 @@ int i; SessionBuffer buf = {0, 0, 0}; sessionAppendStr(&buf, "INSERT INTO main.", &rc); sessionAppendIdent(&buf, zTab, &rc); - sessionAppendStr(&buf, "(", &rc); - for(i=0; inCol; i++){ - if( i!=0 ) sessionAppendStr(&buf, ", ", &rc); - sessionAppendIdent(&buf, p->azCol[i], &rc); - } - - sessionAppendStr(&buf, ") VALUES(?", &rc); + sessionAppendStr(&buf, " VALUES(?", &rc); for(i=1; inCol; i++){ sessionAppendStr(&buf, ", ?", &rc); } sessionAppendStr(&buf, ")", &rc); @@ -178205,51 +175764,42 @@ break; } nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ - int nMinCol = 0; - int i; - sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo( db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK ); if( rc!=SQLITE_OK ) break; - for(i=0; i */ /* #include */ @@ -178864,19 +176414,17 @@ ** to pass signed char values. */ #ifdef sqlite3Isdigit /* Use the SQLite core versions if this routine is part of the ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) -# define safe_isxdigit(x) sqlite3Isxdigit(x) +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) #else /* Use the standard library for separate compilation */ #include /* amalgamator: keep */ -# define safe_isdigit(x) isdigit((unsigned char)(x)) -# define safe_isalnum(x) isalnum((unsigned char)(x)) -# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) #endif /* ** Growing our own isspace() routine this way is twice as fast as ** the library isspace() function, resulting in a 7% overall performance @@ -178953,28 +176501,26 @@ /* Bit values for the JsonNode.jnFlag field */ #define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ #define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ #define JNODE_REMOVE 0x04 /* Do not output */ -#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */ -#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */ -#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ -#define JNODE_LABEL 0x40 /* Is a label of an object */ +#define JNODE_REPLACE 0x08 /* Replace with JsonNode.iVal */ +#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */ +#define JNODE_LABEL 0x20 /* Is a label of an object */ /* A single node of parsed JSON */ struct JsonNode { u8 eType; /* One of the JSON_ type values */ u8 jnFlags; /* JNODE flags */ + u8 iVal; /* Replacement value when JNODE_REPLACE */ u32 n; /* Bytes of content, or number of sub-nodes */ union { const char *zJContent; /* Content for INT, REAL, and STRING */ u32 iAppend; /* More terms for ARRAY and OBJECT */ u32 iKey; /* Key for ARRAY objects in json_tree() */ - u32 iReplace; /* Replacement content for JNODE_REPLACE */ - JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */ } u; }; /* A completely parsed JSON string */ @@ -179227,17 +176773,10 @@ static void jsonRenderNode( JsonNode *pNode, /* The node to render */ JsonString *pOut, /* Write JSON here */ sqlite3_value **aReplace /* Replacement values */ ){ - if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){ - if( pNode->jnFlags & JNODE_REPLACE ){ - jsonAppendValue(pOut, aReplace[pNode->u.iReplace]); - return; - } - pNode = pNode->u.pPatch; - } switch( pNode->eType ){ default: { assert( pNode->eType==JSON_NULL ); jsonAppendRaw(pOut, "null", 4); break; @@ -179265,11 +176804,16 @@ case JSON_ARRAY: { u32 j = 1; jsonAppendChar(pOut, '['); for(;;){ while( j<=pNode->n ){ - if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){ + if( pNode[j].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ){ + if( pNode[j].jnFlags & JNODE_REPLACE ){ + jsonAppendSeparator(pOut); + jsonAppendValue(pOut, aReplace[pNode[j].iVal]); + } + }else{ jsonAppendSeparator(pOut); jsonRenderNode(&pNode[j], pOut, aReplace); } j += jsonNodeSize(&pNode[j]); } @@ -179287,11 +176831,15 @@ while( j<=pNode->n ){ if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ jsonAppendSeparator(pOut); jsonRenderNode(&pNode[j], pOut, aReplace); jsonAppendChar(pOut, ':'); - jsonRenderNode(&pNode[j+1], pOut, aReplace); + if( pNode[j+1].jnFlags & JNODE_REPLACE ){ + jsonAppendValue(pOut, aReplace[pNode[j+1].iVal]); + }else{ + jsonRenderNode(&pNode[j+1], pOut, aReplace); + } } j += 1 + jsonNodeSize(&pNode[j+1]); } if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; pNode = &pNode[pNode->u.iAppend]; @@ -179410,17 +176958,16 @@ zOut[j++] = c; }else{ c = z[++i]; if( c=='u' ){ u32 v = 0, k; - for(k=0; k<4; i++, k++){ - assert( i='0' && c<='9' ) v = v*16 + c - '0'; + else if( c>='A' && c<='F' ) v = v*16 + c - 'A' + 10; + else if( c>='a' && c<='f' ) v = v*16 + c - 'a' + 10; + else break; } if( v==0 ) break; if( v<=0x7f ){ zOut[j++] = (char)v; }else if( v<=0x7ff ){ @@ -179514,24 +177061,16 @@ return jsonParseAddNodeExpand(pParse, eType, n, zContent); } p = &pParse->aNode[pParse->nNode]; p->eType = (u8)eType; p->jnFlags = 0; + p->iVal = 0; p->n = n; p->u.zJContent = zContent; return pParse->nNode++; } -/* -** Return true if z[] begins with 4 (or more) hexadecimal digits -*/ -static int jsonIs4Hex(const char *z){ - int i; - for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; - return 1; -} - /* ** Parse a single JSON value which begins at pParse->zJson[i]. Return the ** index of the first character past the end of the value parsed. ** ** Return negative for a syntax error. Special cases: return -2 if the @@ -179602,17 +177141,12 @@ for(;;){ c = pParse->zJson[j]; if( c==0 ) return -1; if( c=='\\' ){ c = pParse->zJson[++j]; - if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' - || c=='n' || c=='r' || c=='t' - || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){ - jnFlags = JNODE_ESCAPE; - }else{ - return -1; - } + if( c==0 ) return -1; + jnFlags = JNODE_ESCAPE; }else if( c=='"' ){ break; } j++; } @@ -179979,29 +177513,10 @@ zFuncName); sqlite3_result_error(pCtx, zMsg, -1); sqlite3_free(zMsg); } -/* -** Mark all NULL entries in the Object passed in as JNODE_REMOVE. -*/ -static void jsonRemoveAllNulls(JsonNode *pNode){ - int i, n; - assert( pNode->eType==JSON_OBJECT ); - n = pNode->n; - for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){ - switch( pNode[i].eType ){ - case JSON_NULL: - pNode[i].jnFlags |= JNODE_REMOVE; - break; - case JSON_OBJECT: - jsonRemoveAllNulls(&pNode[i]); - break; - } - } -} - /**************************************************************************** ** SQL functions used for testing and debugging ****************************************************************************/ @@ -180189,109 +177704,10 @@ sqlite3_result_subtype(ctx, JSON_SUBTYPE); } jsonReset(&jx); jsonParseReset(&x); } - -/* This is the RFC 7396 MergePatch algorithm. -*/ -static JsonNode *jsonMergePatch( - JsonParse *pParse, /* The JSON parser that contains the TARGET */ - int iTarget, /* Node of the TARGET in pParse */ - JsonNode *pPatch /* The PATCH */ -){ - u32 i, j; - u32 iRoot; - JsonNode *pTarget; - if( pPatch->eType!=JSON_OBJECT ){ - return pPatch; - } - assert( iTarget>=0 && iTargetnNode ); - pTarget = &pParse->aNode[iTarget]; - assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); - if( pTarget->eType!=JSON_OBJECT ){ - jsonRemoveAllNulls(pPatch); - return pPatch; - } - iRoot = iTarget; - for(i=1; in; i += jsonNodeSize(&pPatch[i+1])+1){ - u32 nKey; - const char *zKey; - assert( pPatch[i].eType==JSON_STRING ); - assert( pPatch[i].jnFlags & JNODE_LABEL ); - nKey = pPatch[i].n; - zKey = pPatch[i].u.zJContent; - assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); - for(j=1; jn; j += jsonNodeSize(&pTarget[j+1])+1 ){ - assert( pTarget[j].eType==JSON_STRING ); - assert( pTarget[j].jnFlags & JNODE_LABEL ); - assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); - if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){ - if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break; - if( pPatch[i+1].eType==JSON_NULL ){ - pTarget[j+1].jnFlags |= JNODE_REMOVE; - }else{ - JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]); - if( pNew==0 ) return 0; - pTarget = &pParse->aNode[iTarget]; - if( pNew!=&pTarget[j+1] ){ - pTarget[j+1].u.pPatch = pNew; - pTarget[j+1].jnFlags |= JNODE_PATCH; - } - } - break; - } - } - if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ - int iStart, iPatch; - iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); - jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); - iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); - if( pParse->oom ) return 0; - jsonRemoveAllNulls(pPatch); - pTarget = &pParse->aNode[iTarget]; - pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; - pParse->aNode[iRoot].u.iAppend = iStart - iRoot; - iRoot = iStart; - pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; - pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; - } - } - return pTarget; -} - -/* -** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON -** object that is the result of running the RFC 7396 MergePatch() algorithm -** on the two arguments. -*/ -static void jsonPatchFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse x; /* The JSON that is being patched */ - JsonParse y; /* The patch */ - JsonNode *pResult; /* The result of the merge */ - - UNUSED_PARAM(argc); - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; - if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ - jsonParseReset(&x); - return; - } - pResult = jsonMergePatch(&x, 0, y.aNode); - assert( pResult!=0 || x.oom ); - if( pResult ){ - jsonReturnJson(pResult, ctx, 0); - }else{ - sqlite3_result_error_nomem(ctx); - } - jsonParseReset(&x); - jsonParseReset(&y); -} - /* ** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON ** object that contains all name/value given in arguments. Or if any name ** is not a string or if any value is a BLOB, throw an error. @@ -180392,15 +177808,15 @@ zPath = (const char*)sqlite3_value_text(argv[i]); pNode = jsonLookup(&x, zPath, 0, ctx); if( x.nErr ) goto replace_err; if( pNode ){ pNode->jnFlags |= (u8)JNODE_REPLACE; - pNode->u.iReplace = i + 1; + pNode->iVal = (u8)(i+1); } } if( x.aNode[0].jnFlags & JNODE_REPLACE ){ - sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + sqlite3_result_value(ctx, argv[x.aNode[0].iVal]); }else{ jsonReturnJson(x.aNode, ctx, argv); } replace_err: jsonParseReset(&x); @@ -180446,15 +177862,15 @@ goto jsonSetDone; }else if( x.nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ pNode->jnFlags |= (u8)JNODE_REPLACE; - pNode->u.iReplace = i + 1; + pNode->iVal = (u8)(i+1); } } if( x.aNode[0].jnFlags & JNODE_REPLACE ){ - sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + sqlite3_result_value(ctx, argv[x.aNode[0].iVal]); }else{ jsonReturnJson(x.aNode, ctx, argv); } jsonSetDone: jsonParseReset(&x); @@ -180594,11 +178010,11 @@ JsonString *pStr; pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); if( pStr ){ jsonAppendChar(pStr, '}'); if( pStr->bErr ){ - if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); assert( pStr->bStatic ); }else{ sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); pStr->bStatic = 1; @@ -180872,13 +178288,13 @@ break; } /* For json_each() path and root are the same so fall through ** into the root case */ } - default: { + case JEACH_ROOT: { const char *zRoot = p->zRoot; - if( zRoot==0 ) zRoot = "$"; + if( zRoot==0 ) zRoot = "$"; sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); break; } case JEACH_JSON: { assert( i==JEACH_JSON ); @@ -181093,11 +178509,10 @@ { "json_array_length", 1, 0, jsonArrayLengthFunc }, { "json_array_length", 2, 0, jsonArrayLengthFunc }, { "json_extract", -1, 0, jsonExtractFunc }, { "json_insert", -1, 0, jsonSetFunc }, { "json_object", -1, 0, jsonObjectFunc }, - { "json_patch", 2, 0, jsonPatchFunc }, { "json_quote", 1, 0, jsonQuoteFunc }, { "json_remove", -1, 0, jsonRemoveFunc }, { "json_replace", -1, 0, jsonReplaceFunc }, { "json_set", -1, 1, jsonSetFunc }, { "json_type", 1, 0, jsonTypeFunc }, @@ -181787,13 +179202,11 @@ typedef unsigned short u16; typedef short i16; typedef sqlite3_int64 i64; typedef sqlite3_uint64 u64; -#ifndef ArraySize -# define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) -#endif +#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) #define testcase(x) #define ALWAYS(x) 1 #define NEVER(x) 0 @@ -183008,35 +180421,10 @@ */ #ifndef fts5YYMALLOCARGTYPE # define fts5YYMALLOCARGTYPE size_t #endif -/* Initialize a new parser that has already been allocated. -*/ -static void sqlite3Fts5ParserInit(void *fts5yypParser){ - fts5yyParser *pParser = (fts5yyParser*)fts5yypParser; -#ifdef fts5YYTRACKMAXSTACKDEPTH - pParser->fts5yyhwm = 0; -#endif -#if fts5YYSTACKDEPTH<=0 - pParser->fts5yytos = NULL; - pParser->fts5yystack = NULL; - pParser->fts5yystksz = 0; - if( fts5yyGrowStack(pParser) ){ - pParser->fts5yystack = &pParser->fts5yystk0; - pParser->fts5yystksz = 1; - } -#endif -#ifndef fts5YYNOERRORRECOVERY - pParser->fts5yyerrcnt = -1; -#endif - pParser->fts5yytos = pParser->fts5yystack; - pParser->fts5yystack[0].stateno = 0; - pParser->fts5yystack[0].major = 0; -} - -#ifndef sqlite3Fts5Parser_ENGINEALWAYSONSTACK /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** @@ -183048,15 +180436,32 @@ ** to sqlite3Fts5Parser and sqlite3Fts5ParserFree. */ static void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(fts5YYMALLOCARGTYPE)){ fts5yyParser *pParser; pParser = (fts5yyParser*)(*mallocProc)( (fts5YYMALLOCARGTYPE)sizeof(fts5yyParser) ); - if( pParser ) sqlite3Fts5ParserInit(pParser); + if( pParser ){ +#ifdef fts5YYTRACKMAXSTACKDEPTH + pParser->fts5yyhwm = 0; +#endif +#if fts5YYSTACKDEPTH<=0 + pParser->fts5yytos = NULL; + pParser->fts5yystack = NULL; + pParser->fts5yystksz = 0; + if( fts5yyGrowStack(pParser) ){ + pParser->fts5yystack = &pParser->fts5yystk0; + pParser->fts5yystksz = 1; + } +#endif +#ifndef fts5YYNOERRORRECOVERY + pParser->fts5yyerrcnt = -1; +#endif + pParser->fts5yytos = pParser->fts5yystack; + pParser->fts5yystack[0].stateno = 0; + pParser->fts5yystack[0].major = 0; + } return pParser; } -#endif /* sqlite3Fts5Parser_ENGINEALWAYSONSTACK */ - /* The following function deletes the "minor type" or semantic value ** associated with a symbol. The symbol can be either a terminal ** or nonterminal. "fts5yymajor" is the symbol code, and "fts5yypminor" is ** a pointer to the value to be deleted. The code used to do the @@ -183134,22 +180539,10 @@ } #endif fts5yy_destructor(pParser, fts5yytos->major, &fts5yytos->minor); } -/* -** Clear all secondary memory allocations from the parser -*/ -static void sqlite3Fts5ParserFinalize(void *p){ - fts5yyParser *pParser = (fts5yyParser*)p; - while( pParser->fts5yytos>pParser->fts5yystack ) fts5yy_pop_parser_stack(pParser); -#if fts5YYSTACKDEPTH<=0 - if( pParser->fts5yystack!=&pParser->fts5yystk0 ) free(pParser->fts5yystack); -#endif -} - -#ifndef sqlite3Fts5Parser_ENGINEALWAYSONSTACK /* ** Deallocate and destroy a parser. Destructors are called for ** all stack elements before shutting the parser down. ** ** If the fts5YYPARSEFREENEVERNULL macro exists (for example because it @@ -183158,17 +180551,20 @@ */ static void sqlite3Fts5ParserFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ + fts5yyParser *pParser = (fts5yyParser*)p; #ifndef fts5YYPARSEFREENEVERNULL - if( p==0 ) return; + if( pParser==0 ) return; +#endif + while( pParser->fts5yytos>pParser->fts5yystack ) fts5yy_pop_parser_stack(pParser); +#if fts5YYSTACKDEPTH<=0 + if( pParser->fts5yystack!=&pParser->fts5yystk0 ) free(pParser->fts5yystack); #endif - sqlite3Fts5ParserFinalize(p); - (*freeProc)(p); + (*freeProc)((void*)pParser); } -#endif /* sqlite3Fts5Parser_ENGINEALWAYSONSTACK */ /* ** Return the peak depth of the stack for a parser. */ #ifdef fts5YYTRACKMAXSTACKDEPTH @@ -183275,10 +180671,11 @@ /* ** The following routine is called if the stack overflows. */ static void fts5yyStackOverflow(fts5yyParser *fts5yypParser){ sqlite3Fts5ParserARG_FETCH; + fts5yypParser->fts5yytos--; #ifndef NDEBUG if( fts5yyTraceFILE ){ fprintf(fts5yyTraceFILE,"%sStack Overflow!\n",fts5yyTracePrompt); } #endif @@ -183329,18 +180726,16 @@ assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack) ); } #endif #if fts5YYSTACKDEPTH>0 if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5YYSTACKDEPTH] ){ - fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; } #else if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz] ){ if( fts5yyGrowStack(fts5yypParser) ){ - fts5yypParser->fts5yytos--; fts5yyStackOverflow(fts5yypParser); return; } } #endif @@ -186648,65 +184043,52 @@ /* ** Initialize all term iterators in the pNear object. If any term is found ** to match no documents at all, return immediately without initializing any ** further iterators. -** -** If an error occurs, return an SQLite error code. Otherwise, return -** SQLITE_OK. It is not considered an error if some term matches zero -** documents. */ static int fts5ExprNearInitAll( Fts5Expr *pExpr, Fts5ExprNode *pNode ){ Fts5ExprNearset *pNear = pNode->pNear; - int i; + int i, j; + int rc = SQLITE_OK; + int bEof = 1; assert( pNode->bNomatch==0 ); - for(i=0; inPhrase; i++){ + for(i=0; rc==SQLITE_OK && inPhrase; i++){ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - if( pPhrase->nTerm==0 ){ - pNode->bEof = 1; - return SQLITE_OK; - }else{ - int j; - for(j=0; jnTerm; j++){ - Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; - Fts5ExprTerm *p; - int bHit = 0; - - for(p=pTerm; p; p=p->pSynonym){ - int rc; - if( p->pIter ){ - sqlite3Fts5IterClose(p->pIter); - p->pIter = 0; - } - rc = sqlite3Fts5IndexQuery( - pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), - (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | - (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), - pNear->pColset, - &p->pIter - ); - assert( (rc==SQLITE_OK)==(p->pIter!=0) ); - if( rc!=SQLITE_OK ) return rc; - if( 0==sqlite3Fts5IterEof(p->pIter) ){ - bHit = 1; - } - } - - if( bHit==0 ){ - pNode->bEof = 1; - return SQLITE_OK; - } - } - } - } - - pNode->bEof = 0; - return SQLITE_OK; + for(j=0; jnTerm; j++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; + Fts5ExprTerm *p; + + for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){ + if( p->pIter ){ + sqlite3Fts5IterClose(p->pIter); + p->pIter = 0; + } + rc = sqlite3Fts5IndexQuery( + pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), + (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | + (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), + pNear->pColset, + &p->pIter + ); + assert( rc==SQLITE_OK || p->pIter==0 ); + if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){ + bEof = 0; + } + } + + if( bEof ) break; + } + if( bEof ) break; + } + + pNode->bEof = bEof; + return rc; } /* ** If pExpr is an ASC iterator, this function returns a value with the ** same sign as: @@ -186835,11 +184217,11 @@ pNode->bEof = 1; return rc; } }else{ Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; - if( pIter->iRowid==iLast || pIter->bEof ) continue; + if( pIter->iRowid==iLast ) continue; bMatch = 0; if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ return rc; } } @@ -187012,14 +184394,11 @@ if( p1->bEof==0 ){ if( (p1->iRowid==iLast) || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) ){ int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); - if( rc!=SQLITE_OK ){ - pNode->bNomatch = 0; - return rc; - } + if( rc!=SQLITE_OK ) return rc; } } } fts5ExprNodeTest_OR(pExpr, pNode); @@ -187046,14 +184425,11 @@ Fts5ExprNode *pChild = pAnd->apChild[iChild]; int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); if( cmp>0 ){ /* Advance pChild until it points to iLast or laster */ rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); - if( rc!=SQLITE_OK ){ - pAnd->bNomatch = 0; - return rc; - } + if( rc!=SQLITE_OK ) return rc; } /* If the child node is now at EOF, so is the parent AND node. Otherwise, ** the child node is guaranteed to have advanced at least as far as ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the @@ -187088,12 +184464,10 @@ i64 iFrom ){ int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); if( rc==SQLITE_OK ){ rc = fts5ExprNodeTest_AND(pExpr, pNode); - }else{ - pNode->bNomatch = 0; } return rc; } static int fts5ExprNodeTest_NOT( @@ -187132,13 +184506,10 @@ ){ int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); if( rc==SQLITE_OK ){ rc = fts5ExprNodeTest_NOT(pExpr, pNode); } - if( rc!=SQLITE_OK ){ - pNode->bNomatch = 0; - } return rc; } /* ** If pNode currently points to a match, this function returns SQLITE_OK @@ -187257,14 +184628,11 @@ p->bDesc = bDesc; rc = fts5ExprNodeFirst(p, pRoot); /* If not at EOF but the current rowid occurs earlier than iFirst in ** the iteration order, move to document iFirst or later. */ - if( rc==SQLITE_OK - && 0==pRoot->bEof - && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 - ){ + if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); } /* If the iterator is not at a real match, skip forward until it is. */ while( pRoot->bNomatch ){ @@ -187514,11 +184882,11 @@ memset(&sCtx, 0, sizeof(TokenCtx)); sCtx.pPhrase = pAppend; rc = fts5ParseStringFromToken(pToken, &z); if( rc==SQLITE_OK ){ - int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_PREFIX : 0); + int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0); int n; sqlite3Fts5Dequote(z); n = (int)strlen(z); rc = sqlite3Fts5Tokenize(pConfig, flags, z, n, &sCtx, fts5ParseTokenize); } @@ -191188,11 +188556,11 @@ } } else if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( &pLeaf->p[pLeaf->szLeaf], iOff - ); + ); pIter->iLeafOffset = iOff; pIter->iEndofDoclist = iOff; bNewTerm = 1; } assert_nc( iOffszLeaf ); @@ -191222,11 +188590,10 @@ ** Later: Switched back to fts5SegIterLoadNPos() because it supports ** detail=none mode. Not ideal. */ int nSz; assert( p->rc==SQLITE_OK ); - assert( pIter->iLeafOffset<=pIter->pLeaf->nn ); fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; assert_nc( pIter->nPos>=0 ); } @@ -191990,11 +189357,10 @@ Fts5Iter *pIter, int bFrom, /* True if argument iFrom is valid */ i64 iFrom /* Advance at least as far as this */ ){ int bUseFrom = bFrom; - assert( pIter->base.bEof==0 ); while( p->rc==SQLITE_OK ){ int iFirst = pIter->aFirst[1].iFirst; int bNewTerm = 0; Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; assert( p->rc==SQLITE_OK ); @@ -192217,11 +189583,11 @@ fts5DataRelease(pData); if( nRem<=0 ){ break; }else{ pgno++; - pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); + pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); if( pData==0 ) break; pChunk = &pData->p[4]; nChunk = MIN(nRem, pData->szLeaf - 4); if( pgno==pgnoSave ){ assert( pSeg->pNextLeaf==0 ); @@ -194979,11 +192345,11 @@ /* If the leaf in question has already been trimmed from the segment, ** ignore this b-tree entry. Otherwise, load it into memory. */ if( iIdxLeafpgnoFirst ) continue; iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf); - pLeaf = fts5LeafRead(p, iRow); + pLeaf = fts5DataRead(p, iRow); if( pLeaf==0 ) break; /* Check that the leaf contains at least one term, and that it is equal ** to or larger than the split-key in zIdxTerm. Also check that if there ** is also a rowid pointer within the leaf page header, it points to a @@ -198255,11 +195621,11 @@ int nArg, /* Number of args */ sqlite3_value **apUnused /* Function arguments */ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2017-03-28 18:48:43 424a0d380332858ee55bdebc4af3789f74e70a2b3ba1cf29d84b9b4bcf3e2e37", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2016-11-04 12:08:49 1136863c76576110e710dd5d69ab6bf347c65e36", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { /* iVersion */ 2, @@ -198917,10 +196283,15 @@ sqlite3_bind_int64(pDel, 1, iDel); sqlite3_step(pDel); rc = sqlite3_reset(pDel); } } + + /* Write the averages record */ + if( rc==SQLITE_OK ){ + rc = fts5StorageSaveTotals(p); + } return rc; } /* @@ -199120,10 +196491,15 @@ /* Write the %_docsize record */ if( rc==SQLITE_OK ){ rc = fts5StorageInsertDocsize(p, iRowid, &buf); } sqlite3_free(buf.p); + + /* Write the averages record */ + if( rc==SQLITE_OK ){ + rc = fts5StorageSaveTotals(p); + } return rc; } static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){ @@ -199455,21 +196831,16 @@ /* ** Flush any data currently held in-memory to disk. */ static int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ - int rc = SQLITE_OK; - i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db); - if( p->bTotalsValid ){ - rc = fts5StorageSaveTotals(p); - if( bCommit ) p->bTotalsValid = 0; - } - if( rc==SQLITE_OK ){ - rc = sqlite3Fts5IndexSync(p->pIndex, bCommit); - } - sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid); - return rc; + if( bCommit && p->bTotalsValid ){ + int rc = fts5StorageSaveTotals(p); + p->bTotalsValid = 0; + if( rc!=SQLITE_OK ) return rc; + } + return sqlite3Fts5IndexSync(p->pIndex, bCommit); } static int sqlite3Fts5StorageRollback(Fts5Storage *p){ p->bTotalsValid = 0; return sqlite3Fts5IndexRollback(p->pIndex); Index: sqlite3/src/main/jni/sqlite/sqlite3.h ================================================================== --- sqlite3/src/main/jni/sqlite/sqlite3.h +++ sqlite3/src/main/jni/sqlite/sqlite3.h @@ -112,24 +112,24 @@ ** SQLite source code has been stored in the ** Fossil configuration management ** system. ^The SQLITE_SOURCE_ID macro evaluates to ** a string which identifies a particular check-in of SQLite ** within its configuration management system. ^The SQLITE_SOURCE_ID -** string contains the date and time of the check-in (UTC) and a SHA1 -** or SHA3-256 hash of the entire source tree. +** string contains the date and time of the check-in (UTC) and an SHA1 +** hash of the entire source tree. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.18.0" -#define SQLITE_VERSION_NUMBER 3018000 -#define SQLITE_SOURCE_ID "2017-03-28 18:48:43 424a0d380332858ee55bdebc4af3789f74e70a2b3ba1cf29d84b9b4bcf3e2e37" +#define SQLITE_VERSION "3.15.1" +#define SQLITE_VERSION_NUMBER 3015001 +#define SQLITE_SOURCE_ID "2016-11-04 12:08:49 1136863c76576110e710dd5d69ab6bf347c65e36" /* ** CAPI3REF: Run-Time Library Version Numbers -** KEYWORDS: sqlite3_version sqlite3_sourceid +** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ** but are associated with the library instead of the header file. ^(Cautious ** programmers might include assert() statements in their application to @@ -257,15 +257,11 @@ ** sqlite3_uint64 and sqlite_uint64 types can store integer values ** between 0 and +18446744073709551615 inclusive. */ #ifdef SQLITE_INT64_TYPE typedef SQLITE_INT64_TYPE sqlite_int64; -# ifdef SQLITE_UINT64_TYPE - typedef SQLITE_UINT64_TYPE sqlite_uint64; -# else - typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; -# endif + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; #elif defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 sqlite_int64; typedef unsigned __int64 sqlite_uint64; #else typedef long long int sqlite_int64; @@ -574,11 +570,11 @@ ** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that ** after reboot following a crash or power loss, the only bytes in a ** file that were written at the application level might have changed ** and that adjacent bytes, even bytes within the same sector are ** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN -** flag indicates that a file cannot be deleted when open. The +** flag indicate that a file cannot be deleted when open. The ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on ** read-only media and cannot be changed even by processes with ** elevated privileges. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 @@ -724,13 +720,10 @@ **
  • [SQLITE_IOCAP_ATOMIC16K] **
  • [SQLITE_IOCAP_ATOMIC32K] **
  • [SQLITE_IOCAP_ATOMIC64K] **
  • [SQLITE_IOCAP_SAFE_APPEND] **
  • [SQLITE_IOCAP_SEQUENTIAL] -**
  • [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] -**
  • [SQLITE_IOCAP_POWERSAFE_OVERWRITE] -**
  • [SQLITE_IOCAP_IMMUTABLE] ** ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and @@ -1040,11 +1033,10 @@ #define SQLITE_FCNTL_ZIPVFS 25 #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 -#define SQLITE_FCNTL_PDB 30 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO @@ -1993,31 +1985,18 @@ ** does not make a copy of the new main schema name string, so the application ** must ensure that the argument passed into this DBCONFIG option is unchanged ** until after the database connection closes. **
  • ** -**
    SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
    -**
    Usually, when a database in wal mode is closed or detached from a -** database handle, SQLite checks if this will mean that there are now no -** connections at all to the database. If so, it performs a checkpoint -** operation before closing the connection. This option may be used to -** override this behaviour. The first parameter passed to this operation -** is an integer - non-zero to disable checkpoints-on-close, or zero (the -** default) to enable them. The second parameter is a pointer to an integer -** into which is written 0 or 1 to indicate whether checkpoints-on-close -** have been disabled - 0 if they are not disabled, 1 if they are. -**
    -** ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ -#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 @@ -2038,34 +2017,24 @@ ** as an undeclared column named ROWID, OID, or _ROWID_ as long as those ** names are not also used by explicitly declared columns. ^If ** the table has a column of type [INTEGER PRIMARY KEY] then that column ** is another alias for the rowid. ** -** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of -** the most recent successful [INSERT] into a rowid table or [virtual table] -** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not -** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred -** on the database connection D, then sqlite3_last_insert_rowid(D) returns -** zero. -** -** As well as being set automatically as rows are inserted into database -** tables, the value returned by this function may be set explicitly by -** [sqlite3_set_last_insert_rowid()] -** -** Some virtual table implementations may INSERT rows into rowid tables as -** part of committing a transaction (e.g. to flush data accumulated in memory -** to disk). In this case subsequent calls to this function return the rowid -** associated with these internal INSERT operations, which leads to -** unintuitive results. Virtual table implementations that do write to rowid -** tables in this way can avoid this problem by restoring the original -** rowid value using [sqlite3_set_last_insert_rowid()] before returning -** control to the user. -** -** ^(If an [INSERT] occurs within a trigger then this routine will -** return the [rowid] of the inserted row as long as the trigger is -** running. Once the trigger program ends, the value returned -** by this routine reverts to what it was before the trigger was fired.)^ +** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the +** most recent successful [INSERT] into a rowid table or [virtual table] +** on database connection D. +** ^Inserts into [WITHOUT ROWID] tables are not recorded. +** ^If no successful [INSERT]s into rowid tables +** have ever occurred on the database connection D, +** then sqlite3_last_insert_rowid(D) returns zero. +** +** ^(If an [INSERT] occurs within a trigger or within a [virtual table] +** method, then this routine will return the [rowid] of the inserted +** row as long as the trigger or virtual table method is running. +** But once the trigger or virtual table method ends, the value returned +** by this routine reverts to what it was before the trigger or virtual +** table method began.)^ ** ** ^An [INSERT] that fails due to a constraint violation is not a ** successful [INSERT] and does not change the value returned by this ** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, ** and INSERT OR ABORT make no changes to the return value of this @@ -2088,20 +2057,10 @@ ** unpredictable and might not equal either the old or the new ** last insert [rowid]. */ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); -/* -** CAPI3REF: Set the Last Insert Rowid value. -** METHOD: sqlite3 -** -** The sqlite3_set_last_insert_rowid(D, R) method allows the application to -** set the value returned by calling sqlite3_last_insert_rowid(D) to R -** without inserting a row into the database. -*/ -SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); - /* ** CAPI3REF: Count The Number Of Rows Modified ** METHOD: sqlite3 ** ** ^This function returns the number of rows modified, inserted or @@ -3422,13 +3381,13 @@ ** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    **
    The maximum number of terms in a compound SELECT statement.
    )^ ** ** [[SQLITE_LIMIT_VDBE_OP]] ^(
    SQLITE_LIMIT_VDBE_OP
    **
    The maximum number of instructions in a virtual machine program -** used to implement an SQL statement. If [sqlite3_prepare_v2()] or -** the equivalent tries to allocate space for more than this many opcodes -** in a single prepared statement, an SQLITE_NOMEM error is returned.
    )^ +** used to implement an SQL statement. This limit is not currently +** enforced, though that might be added in some future release of +** SQLite.)^ ** ** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
    SQLITE_LIMIT_FUNCTION_ARG
    **
    The maximum number of arguments on a function.
    )^ ** ** [[SQLITE_LIMIT_ATTACHED]] ^(
    SQLITE_LIMIT_ATTACHED
    @@ -3461,11 +3420,10 @@ #define SQLITE_LIMIT_ATTACHED 7 #define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 #define SQLITE_LIMIT_VARIABLE_NUMBER 9 #define SQLITE_LIMIT_TRIGGER_DEPTH 10 #define SQLITE_LIMIT_WORKER_THREADS 11 - /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** METHOD: sqlite3 @@ -3636,14 +3594,10 @@ ** rather they control the timing of when other statements modify the ** database. ^The [ATTACH] and [DETACH] statements also cause ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. -** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since -** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and -** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so -** sqlite3_stmt_readonly() returns false for those commands. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset @@ -3922,16 +3876,12 @@ /* ** CAPI3REF: Number Of Columns In A Result Set ** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the -** [prepared statement]. ^If this routine returns 0, that means the -** [prepared statement] returns no data (for example an [UPDATE]). -** ^However, just because this routine returns a positive number does not -** mean that one or more rows of data will be returned. ^A SELECT statement -** will always have a positive sqlite3_column_count() but depending on the -** WHERE clause constraints and the table content, it might return no rows. +** [prepared statement]. ^This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). ** ** See also: [sqlite3_data_count()] */ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); @@ -5436,11 +5386,11 @@ ** ^(The update hook is not invoked when internal system tables are ** modified (i.e. sqlite_master and sqlite_sequence).)^ ** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. ** ** ^In the current implementation, the update hook -** is not invoked when conflicting rows are deleted because of an +** is not invoked when duplication rows are deleted because of an ** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook ** invoked when rows are deleted using the [truncate optimization]. ** The exceptions defined in this paragraph might change in a future ** release of SQLite. ** @@ -6218,16 +6168,10 @@ ** ** ^Unless it returns SQLITE_MISUSE, this function sets the ** [database connection] error code and message accessible via ** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. ** -** A BLOB referenced by sqlite3_blob_open() may be read using the -** [sqlite3_blob_read()] interface and modified by using -** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a -** different row of the same table using the [sqlite3_blob_reopen()] -** interface. However, the column, table, or database of a [BLOB handle] -** cannot be changed after the [BLOB handle] is opened. ** ** ^(If the row that a BLOB handle points to is modified by an ** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects ** then the BLOB handle is marked as "expired". ** This is true if any column of the row is changed, even a column @@ -6247,14 +6191,10 @@ ** and the built-in [zeroblob] SQL function may be used to create a ** zero-filled blob to read or write using the incremental-blob interface. ** ** To avoid a resource leak, every open [BLOB handle] should eventually ** be released by a call to [sqlite3_blob_close()]. -** -** See also: [sqlite3_blob_close()], -** [sqlite3_blob_reopen()], [sqlite3_blob_read()], -** [sqlite3_blob_bytes()], [sqlite3_blob_write()]. */ SQLITE_API int sqlite3_blob_open( sqlite3*, const char *zDb, const char *zTable, @@ -6266,15 +6206,15 @@ /* ** CAPI3REF: Move a BLOB Handle to a New Row ** METHOD: sqlite3_blob ** -** ^This function is used to move an existing [BLOB handle] so that it points +** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified ** by the rowid value passed as the second argument. Only the row can be ** changed. ^The database, table and column on which the blob handle is open -** remain the same. Moving an existing [BLOB handle] to a new row is +** remain the same. Moving an existing blob handle to a new row can be ** faster than closing the existing handle and opening a new one. ** ** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - ** it must exist and there must be either a blob or text value stored in ** the nominated column.)^ ^If the new row is not present in the table, or if @@ -8199,22 +8139,22 @@ ** ^These interfaces are only available if SQLite is compiled using the ** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. ** ** ^The [sqlite3_preupdate_hook()] interface registers a callback function ** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation -** on a database table. +** on a [rowid table]. ** ^At most one preupdate hook may be registered at a time on a single ** [database connection]; each call to [sqlite3_preupdate_hook()] overrides ** the previous setting. ** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] ** with a NULL pointer as the second parameter. ** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as ** the first parameter to callbacks. ** -** ^The preupdate hook only fires for changes to real database tables; the -** preupdate hook is not invoked for changes to [virtual tables] or to -** system tables like sqlite_master or sqlite_stat1. +** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate +** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID] +** tables. ** ** ^The second parameter to the preupdate callback is a pointer to ** the [database connection] that registered the preupdate hook. ** ^The third parameter to the preupdate callback is one of the constants ** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the @@ -8224,20 +8164,16 @@ ** will be "main" for the main database or "temp" for TEMP tables or ** the name given after the AS keyword in the [ATTACH] statement for attached ** databases.)^ ** ^The fifth parameter to the preupdate callback is the name of the ** table that is being modified. -** -** For an UPDATE or DELETE operation on a [rowid table], the sixth -** parameter passed to the preupdate callback is the initial [rowid] of the -** row being modified or deleted. For an INSERT operation on a rowid table, -** or any operation on a WITHOUT ROWID table, the value of the sixth -** parameter is undefined. For an INSERT or UPDATE on a rowid table the -** seventh parameter is the final rowid value of the row being inserted -** or updated. The value of the seventh parameter passed to the callback -** function is not defined for operations on WITHOUT ROWID tables, or for -** INSERT operations on rowid tables. +** ^The sixth parameter to the preupdate callback is the initial [rowid] of the +** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is +** undefined for SQLITE_INSERT changes. +** ^The seventh parameter to the preupdate callback is the final [rowid] of +** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is +** undefined for SQLITE_DELETE changes. ** ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces ** provide additional information about a preupdate event. These routines ** may only be called from within a preupdate callback. Invoking any of @@ -8273,12 +8209,11 @@ ** triggers; or 2 for changes resulting from triggers called by top-level ** triggers; and so forth. ** ** See also: [sqlite3_update_hook()] */ -#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) -SQLITE_API void *sqlite3_preupdate_hook( +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook( sqlite3 *db, void(*xPreUpdate)( void *pCtx, /* Copy of third arg to preupdate_hook() */ sqlite3 *db, /* Database handle */ int op, /* SQLITE_UPDATE, DELETE or INSERT */ @@ -8287,15 +8222,14 @@ sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ ), void* ); -SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); -SQLITE_API int sqlite3_preupdate_count(sqlite3 *); -SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); -SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); -#endif +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *); +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error @@ -8307,11 +8241,11 @@ */ SQLITE_API int sqlite3_system_errno(sqlite3*); /* ** CAPI3REF: Database Snapshot -** KEYWORDS: {snapshot} {sqlite3_snapshot} +** KEYWORDS: {snapshot} ** EXPERIMENTAL ** ** An instance of the snapshot object records the state of a [WAL mode] ** database for some specific point in history. ** @@ -8331,13 +8265,11 @@ ** The constructor for this object is [sqlite3_snapshot_get()]. The ** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer ** to an historical snapshot (if possible). The destructor for ** sqlite3_snapshot objects is [sqlite3_snapshot_free()]. */ -typedef struct sqlite3_snapshot { - unsigned char hidden[48]; -} sqlite3_snapshot; +typedef struct sqlite3_snapshot sqlite3_snapshot; /* ** CAPI3REF: Record A Database Snapshot ** EXPERIMENTAL ** @@ -8344,36 +8276,13 @@ ** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a ** new [sqlite3_snapshot] object that records the current state of ** schema S in database connection D. ^On success, the ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. -** If there is not already a read-transaction open on schema S when -** this function is called, one is opened automatically. -** -** The following must be true for this function to succeed. If any of -** the following statements are false when sqlite3_snapshot_get() is -** called, SQLITE_ERROR is returned. The final value of *P is undefined -** in this case. -** -**
      -**
    • The database handle must be in [autocommit mode]. -** -**
    • Schema S of [database connection] D must be a [WAL mode] database. -** -**
    • There must not be a write transaction open on schema S of database -** connection D. -** -**
    • One or more transactions must have been written to the current wal -** file since it was created on disk (by any connection). This means -** that a snapshot cannot be taken on a wal mode database with no wal -** file immediately after it is first opened. At least one transaction -** must be written to it first. -**
    -** -** This function may also return SQLITE_NOMEM. If it is called with the -** database handle in autocommit mode but fails for some other reason, -** whether or not a read transaction is opened on schema S is undefined. +** ^If schema S of [database connection] D is not a [WAL mode] database +** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)] +** leaves the *P value unchanged and returns an appropriate [error code]. ** ** The [sqlite3_snapshot] object returned from a successful call to ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] ** to avoid a memory leak. ** @@ -8462,32 +8371,10 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( sqlite3_snapshot *p1, sqlite3_snapshot *p2 ); -/* -** CAPI3REF: Recover snapshots from a wal file -** EXPERIMENTAL -** -** If all connections disconnect from a database file but do not perform -** a checkpoint, the existing wal file is opened along with the database -** file the next time the database is opened. At this point it is only -** possible to successfully call sqlite3_snapshot_open() to open the most -** recent snapshot of the database (the one at the head of the wal file), -** even though the wal file may contain other valid snapshots for which -** clients have sqlite3_snapshot handles. -** -** This function attempts to scan the wal file associated with database zDb -** of database handle db and make all valid snapshots available to -** sqlite3_snapshot_open(). It is an error if there is already a read -** transaction open on the database, or if the database is not a wal mode -** database. -** -** SQLITE_OK is returned if successful, or an SQLite error code otherwise. -*/ -SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); - /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT @@ -8669,11 +8556,11 @@ ** The session object will be used to create changesets for tables in ** database zDb, where zDb is either "main", or "temp", or the name of an ** attached database. It is not an error if database zDb is not attached ** to the database when the session object is created. */ -SQLITE_API int sqlite3session_create( +int sqlite3session_create( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of db (e.g. "main") */ sqlite3_session **ppSession /* OUT: New session object */ ); @@ -8687,11 +8574,11 @@ ** ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ -SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); +void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object ** @@ -8707,11 +8594,11 @@ ** no-op, and may be used to query the current state of the session. ** ** The return value indicates the final state of the session object: 0 if ** the session is disabled, or 1 if it is enabled. */ -SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); +int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag ** ** Each change recorded by a session object is marked as either direct or @@ -8736,11 +8623,11 @@ ** indirect flag for the specified session object. ** ** The return value indicates the final state of the indirect flag: 0 if ** it is clear, or 1 if it is set. */ -SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); +int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); /* ** CAPI3REF: Attach A Table To A Session Object ** ** If argument zTab is not NULL, then it is the name of a table to attach @@ -8766,11 +8653,11 @@ ** in one or more of their PRIMARY KEY columns. ** ** SQLITE_OK is returned if the call completes without error. Or, if an error ** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. */ -SQLITE_API int sqlite3session_attach( +int sqlite3session_attach( sqlite3_session *pSession, /* Session object */ const char *zTab /* Table name */ ); /* @@ -8780,11 +8667,11 @@ ** in tables that are not attached to the Session object, the filter is called ** to determine whether changes to the table's rows should be tracked or not. ** If xFilter returns 0, changes is not tracked. Note that once a table is ** attached, xFilter will not be called again. */ -SQLITE_API void sqlite3session_table_filter( +void sqlite3session_table_filter( sqlite3_session *pSession, /* Session object */ int(*xFilter)( void *pCtx, /* Copy of third arg to _filter_table() */ const char *zTab /* Table name */ ), @@ -8893,11 +8780,11 @@ ** changeset, even though the delete took place while the session was disabled. ** Or, if one field of a row is updated while a session is disabled, and ** another field of the same row is updated while the session is enabled, the ** resulting changeset will contain an UPDATE change that updates both fields. */ -SQLITE_API int sqlite3session_changeset( +int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); @@ -8937,12 +8824,11 @@ ** **
  • For each row (primary key) that exists in the to-table but not in ** the from-table, a DELETE record is added to the session object. ** **
  • For each row (primary key) that exists in both tables, but features -** different non-PK values in each, an UPDATE record is added to the -** session. +** different in each, an UPDATE record is added to the session. ** ** ** To clarify, if this function is called and then a changeset constructed ** using [sqlite3session_changeset()], then after applying that changeset to ** database zFrom the contents of the two compatible tables would be @@ -8955,11 +8841,11 @@ ** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg ** may be set to point to a buffer containing an English language error ** message. It is the responsibility of the caller to free this buffer using ** sqlite3_free(). */ -SQLITE_API int sqlite3session_diff( +int sqlite3session_diff( sqlite3_session *pSession, const char *zFromDb, const char *zTbl, char **pzErrMsg ); @@ -8991,11 +8877,11 @@ ** Changes within a patchset are ordered in the same way as for changesets ** generated by the sqlite3session_changeset() function (i.e. all changes for ** a single table are grouped together, tables appear in the order in which ** they were attached to the session object). */ -SQLITE_API int sqlite3session_patchset( +int sqlite3session_patchset( sqlite3_session *pSession, /* Session object */ int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */ void **ppPatchset /* OUT: Buffer containing changeset */ ); @@ -9012,11 +8898,11 @@ ** an attached table is modified and then later on the original values ** are restored. However, if this function returns non-zero, then it is ** guaranteed that a call to sqlite3session_changeset() will return a ** changeset containing zero changes. */ -SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); +int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset ** ** Create an iterator used to iterate through the contents of a changeset. @@ -9047,11 +8933,11 @@ ** this function, all changes that relate to a single table are visited ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. */ -SQLITE_API int sqlite3changeset_start( +int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); @@ -9076,11 +8962,11 @@ ** ** If an error occurs, an SQLite error code is returned. Possible error ** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or ** SQLITE_NOMEM. */ -SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); +int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator ** ** The pIter argument passed to this function may either be an iterator @@ -9104,11 +8990,11 @@ ** ** If no error occurs, SQLITE_OK is returned. If an error does occur, an ** SQLite error code is returned. The values of the output variables may not ** be trusted in this case. */ -SQLITE_API int sqlite3changeset_op( +int sqlite3changeset_op( sqlite3_changeset_iter *pIter, /* Iterator object */ const char **pzTab, /* OUT: Pointer to table name */ int *pnCol, /* OUT: Number of columns in table */ int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ int *pbIndirect /* OUT: True for an 'indirect' change */ @@ -9137,11 +9023,11 @@ ** If this function is called when the iterator does not point to a valid ** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, ** SQLITE_OK is returned and the output variables populated as described ** above. */ -SQLITE_API int sqlite3changeset_pk( +int sqlite3changeset_pk( sqlite3_changeset_iter *pIter, /* Iterator object */ unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ int *pnCol /* OUT: Number of entries in output array */ ); @@ -9167,11 +9053,11 @@ ** is similar to the "old.*" columns available to update or delete triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ -SQLITE_API int sqlite3changeset_old( +int sqlite3changeset_old( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ ); @@ -9200,11 +9086,11 @@ ** triggers. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ -SQLITE_API int sqlite3changeset_new( +int sqlite3changeset_new( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ ); @@ -9227,11 +9113,11 @@ ** and returns SQLITE_OK. ** ** If some other error occurs (e.g. an OOM condition), an SQLite error code ** is returned and *ppValue is set to NULL. */ -SQLITE_API int sqlite3changeset_conflict( +int sqlite3changeset_conflict( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int iVal, /* Column number */ sqlite3_value **ppValue /* OUT: Value from conflicting row */ ); @@ -9243,11 +9129,11 @@ ** it sets the output variable to the total number of known foreign key ** violations in the destination database and returns SQLITE_OK. ** ** In all other cases this function returns SQLITE_MISUSE. */ -SQLITE_API int sqlite3changeset_fk_conflicts( +int sqlite3changeset_fk_conflicts( sqlite3_changeset_iter *pIter, /* Changeset iterator */ int *pnOut /* OUT: Number of FK violations */ ); @@ -9276,11 +9162,11 @@ ** rc = sqlite3changeset_finalize(); ** if( rc!=SQLITE_OK ){ ** // An error has occurred ** } */ -SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); +int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Invert A Changeset ** ** This function is used to "invert" a changeset object. Applying an inverted @@ -9306,11 +9192,11 @@ ** call to this function. ** ** WARNING/TODO: This function currently assumes that the input is a valid ** changeset. If it is not, the results are undefined. */ -SQLITE_API int sqlite3changeset_invert( +int sqlite3changeset_invert( int nIn, const void *pIn, /* Input changeset */ int *pnOut, void **ppOut /* OUT: Inverse of input */ ); /* @@ -9335,11 +9221,11 @@ ** *pnOut = 0; ** } ** ** Refer to the sqlite3_changegroup documentation below for details. */ -SQLITE_API int sqlite3changeset_concat( +int sqlite3changeset_concat( int nA, /* Number of bytes in buffer pA */ void *pA, /* Pointer to buffer containing changeset A */ int nB, /* Number of bytes in buffer pB */ void *pB, /* Pointer to buffer containing changeset B */ int *pnOut, /* OUT: Number of bytes in output changeset */ @@ -9523,11 +9409,11 @@ ** considered compatible if all of the following are true: ** **
      **
    • The table has the same name as the name recorded in the ** changeset, and -**
    • The table has at least as many columns as recorded in the +**
    • The table has the same number of columns as recorded in the ** changeset, and **
    • The table has primary key columns in the same position as ** recorded in the changeset. **
    ** @@ -9568,15 +9454,11 @@ ** the changeset the row is deleted from the target database. ** ** If a row with matching primary key values is found, but one or more of ** the non-primary key fields contains a value different from the original ** row value stored in the changeset, the conflict-handler function is -** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the -** database table has more columns than are recorded in the changeset, -** only the values of those non-primary key fields are compared against -** the current database contents - any trailing database table columns -** are ignored. +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. ** ** If no row with matching primary key values is found in the database, ** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] ** passed as the second argument. ** @@ -9587,13 +9469,11 @@ ** operation is attempted because an earlier call to the conflict handler ** function returned [SQLITE_CHANGESET_REPLACE]. ** **
    INSERT Changes
    ** For each INSERT change, an attempt is made to insert the new row into -** the database. If the changeset row contains fewer fields than the -** database table, the trailing fields are populated with their default -** values. +** the database. ** ** If the attempt to insert the row fails because the database already ** contains a row with the same primary key values, the conflict handler ** function is invoked with the second argument set to ** [SQLITE_CHANGESET_CONFLICT]. @@ -9607,17 +9487,17 @@ ** **
    UPDATE Changes
    ** For each UPDATE change, this function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values -** stored in all modified non-primary key columns also match the values -** stored in the changeset the row is updated within the target database. +** stored in all non-primary key columns also match the values stored in +** the changeset the row is updated within the target database. ** ** If a row with matching primary key values is found, but one or more of -** the modified non-primary key fields contains a value different from an -** original row value stored in the changeset, the conflict-handler function -** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since +** the non-primary key fields contains a value different from an original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since ** UPDATE changes only contain values for non-primary key fields that are ** to be modified, only those fields need to match the original values to ** avoid the SQLITE_CHANGESET_DATA conflict-handler callback. ** ** If no row with matching primary key values is found in the database, @@ -9641,11 +9521,11 @@ ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. */ -SQLITE_API int sqlite3changeset_apply( +int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ int nChangeset, /* Size of changeset in bytes */ void *pChangeset, /* Changeset blob */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ @@ -9842,11 +9722,11 @@ ** ** The sessions module never invokes an xOutput callback with the third ** parameter set to a value less than or equal to zero. Other than this, ** no guarantees are made as to the size of the chunks of data returned. */ -SQLITE_API int sqlite3changeset_apply_strm( +int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ void *pIn, /* First arg for xInput */ int(*xFilter)( void *pCtx, /* Copy of sixth arg to _apply() */ @@ -9857,35 +9737,35 @@ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), void *pCtx /* First argument passed to xConflict */ ); -SQLITE_API int sqlite3changeset_concat_strm( +int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, int (*xInputB)(void *pIn, void *pData, int *pnData), void *pInB, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3changeset_invert_strm( +int sqlite3changeset_invert_strm( int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3changeset_start_strm( +int sqlite3changeset_start_strm( sqlite3_changeset_iter **pp, int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); -SQLITE_API int sqlite3session_changeset_strm( +int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); -SQLITE_API int sqlite3session_patchset_strm( +int sqlite3session_patchset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); int sqlite3changegroup_add_strm(sqlite3_changegroup*, Index: sqlite3test/build.gradle ================================================================== --- sqlite3test/build.gradle +++ sqlite3test/build.gradle @@ -1,28 +1,27 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion '25.0.2' + compileSdkVersion 23 + buildToolsVersion '24.0.3' + defaultConfig { applicationId "org.sqlite.customsqlitetest" - minSdkVersion 9 - targetSdkVersion 25 + minSdkVersion 16 + targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - productFlavors { - } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' - compile 'com.android.support:appcompat-v7:25.3.1' + compile 'com.android.support:appcompat-v7:23.4.0' compile project(':sqlite3') } Index: sqlite3test/src/main/java/org/sqlite/customsqlitetest/MainActivity.java ================================================================== --- sqlite3test/src/main/java/org/sqlite/customsqlitetest/MainActivity.java +++ sqlite3test/src/main/java/org/sqlite/customsqlitetest/MainActivity.java @@ -6,11 +6,10 @@ import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; -import org.json.JSONObject; import org.sqlite.database.DatabaseErrorHandler; import org.sqlite.database.sqlite.SQLiteDatabase; import org.sqlite.database.sqlite.SQLiteStatement; import org.sqlite.database.sqlite.SQLiteDatabaseCorruptException; import org.sqlite.database.sqlite.SQLiteOpenHelper; @@ -50,24 +49,22 @@ db = SQLiteDatabase.openOrCreateDatabase(":memory:", null); st = db.compileStatement("SELECT sqlite_version()"); res = st.simpleQueryForString(); myTV.append("SQLite version " + res + "\n\n"); - db.close(); } public void test_warning(String name, String warning){ myTV.append("WARNING:" + name + ": " + warning + "\n"); } - public void test_result(String name, String res, String expected, long t0){ - long tot = (System.nanoTime() - t0) / 1000000; + public void test_result(String name, String res, String expected){ myTV.append(name + "... "); myNTest++; if( res.equals(expected) ){ - myTV.append("ok (" + tot + "ms)\n"); + myTV.append("ok\n"); } else { myNErr++; myTV.append("FAILED\n"); myTV.append(" res= \"" + res + "\"\n"); myTV.append(" expected=\"" + expected + "\"\n"); @@ -107,30 +104,27 @@ db.execSQL("CREATE TABLE t1(x, y)"); db.execSQL("INSERT INTO t1 VALUES (1, 2), (3, 4)"); Thread t = new Thread( new Runnable() { public void run() { - final long t0 = System.nanoTime(); SQLiteStatement st = db.compileStatement("SELECT sum(x+y) FROM t1"); String res = st.simpleQueryForString(); - test_result("thread_test_1", res, "10", t0); + test_result("thread_test_1", res, "10"); } }); t.start(); try { t.join(); } catch (InterruptedException e) { } - db.close(); } /* ** Test that a database connection may be accessed from a second thread. */ public void thread_test_2(){ - final long t0 = System.nanoTime(); SQLiteDatabase.deleteDatabase(DB_PATH); final SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); db.execSQL("CREATE TABLE t1(x, y)"); db.execSQL("INSERT INTO t1 VALUES (1, 2), (3, 4)"); @@ -156,22 +150,20 @@ if( t.isAlive() ){ res = "blocked"; } db.endTransaction(); try { t.join(); } catch(InterruptedException e) {} if( SQLiteDatabase.hasCodec() ){ - test_result("thread_test_2", res, "blocked", t0); + test_result("thread_test_2", res, "blocked"); } else { - test_result("thread_test_2", res, "concurrent", t0); + test_result("thread_test_2", res, "concurrent"); } - db.close(); } /* ** Use a Cursor to loop through the results of a SELECT query. */ public void csr_test_2() throws Exception { - final long t0 = System.nanoTime(); SQLiteDatabase.deleteDatabase(DB_PATH); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); String res = ""; String expect = ""; int i; @@ -192,13 +184,12 @@ res = res + "." + x; } }else{ test_warning("csr_test_1", "c==NULL"); } - test_result("csr_test_2.1", res, expect, t0); + test_result("csr_test_2.1", res, expect); - final long t1 = System.nanoTime(); db.execSQL("BEGIN"); for(i=0; i<1000; i++){ db.execSQL("INSERT INTO t1 VALUES (X'123456'), (X'789ABC'), (X'DEF012')"); db.execSQL("INSERT INTO t1 VALUES (45), (46), (47)"); db.execSQL("INSERT INTO t1 VALUES (8.1), (8.2), (8.3)"); @@ -211,11 +202,11 @@ boolean bRes; for(bRes=c.moveToFirst(); bRes; bRes=c.moveToNext()) nRow++; }else{ test_warning("csr_test_1", "c==NULL"); } - test_result("csr_test_2.2", "" + nRow, "15000", t1); + test_result("csr_test_2.2", "" + nRow, "15000"); db.close(); } public String string_from_t1_x(SQLiteDatabase db){ @@ -229,28 +220,25 @@ } return res; } public void csr_test_1() throws Exception { - final long t0 = System.nanoTime(); SQLiteDatabase.deleteDatabase(DB_PATH); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); String res = ""; db.execSQL("CREATE TABLE t1(x)"); db.execSQL("INSERT INTO t1 VALUES ('one'), ('two'), ('three')"); res = string_from_t1_x(db); - test_result("csr_test_1.1", res, ".one.two.three", t0); - final long t1 = System.nanoTime(); + test_result("csr_test_1.1", res, ".one.two.three"); db.close(); - test_result("csr_test_1.2", db_is_encrypted(), "unencrypted", t1); + test_result("csr_test_1.2", db_is_encrypted(), "unencrypted"); } public void stmt_jrnl_test_1() throws Exception { - final long t0 = System.nanoTime(); SQLiteDatabase.deleteDatabase(DB_PATH); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); String res = ""; db.execSQL("CREATE TABLE t1(x, y UNIQUE)"); @@ -257,16 +245,15 @@ db.execSQL("BEGIN"); db.execSQL("INSERT INTO t1 VALUES(1, 1), (2, 2), (3, 3)"); db.execSQL("UPDATE t1 SET y=y+3"); db.execSQL("COMMIT"); db.close(); - test_result("stmt_jrnl_test_1.1", "did not crash", "did not crash", t0); + test_result("stmt_jrnl_test_1.1", "did not crash", "did not crash"); } public void supp_char_test_1() throws Exception { - final long t0 = System.nanoTime(); SQLiteDatabase.deleteDatabase(DB_PATH); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); String res = ""; String smiley = new String( Character.toChars(0x10000) ); @@ -273,20 +260,19 @@ db.execSQL("CREATE TABLE t1(x)"); db.execSQL("INSERT INTO t1 VALUES ('a" + smiley + "b')"); res = string_from_t1_x(db); - test_result("supp_char_test1." + smiley, res, ".a" + smiley + "b", t0); + test_result("supp_char_test1." + smiley, res, ".a" + smiley + "b"); db.close(); } /* ** If this is a SEE build, check that encrypted databases work. */ public void see_test_1() throws Exception { - final long t0 = System.nanoTime(); if( !SQLiteDatabase.hasCodec() ) return; SQLiteDatabase.deleteDatabase(DB_PATH); String res = ""; @@ -295,22 +281,19 @@ db.execSQL("CREATE TABLE t1(x)"); db.execSQL("INSERT INTO t1 VALUES ('one'), ('two'), ('three')"); res = string_from_t1_x(db); - test_result("see_test_1.1", res, ".one.two.three", t0); - final long t1 = System.nanoTime(); + test_result("see_test_1.1", res, ".one.two.three"); db.close(); - test_result("see_test_1.2", db_is_encrypted(), "encrypted", t1); - final long t2 = System.nanoTime(); + test_result("see_test_1.2", db_is_encrypted(), "encrypted"); db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); db.execSQL("PRAGMA key = 'secretkey'"); res = string_from_t1_x(db); - test_result("see_test_1.3", res, ".one.two.three", t2); - final long t3 = System.nanoTime(); + test_result("see_test_1.3", res, ".one.two.three"); db.close(); res = "unencrypted"; try { db = SQLiteDatabase.openOrCreateDatabase(DB_PATH.getPath(), null); @@ -318,12 +301,11 @@ } catch ( SQLiteDatabaseCorruptException e ){ res = "encrypted"; } finally { db.close(); } - test_result("see_test_1.4", res, "encrypted", t3); - final long t4 = System.nanoTime(); + test_result("see_test_1.4", res, "encrypted"); res = "unencrypted"; try { db = SQLiteDatabase.openOrCreateDatabase(DB_PATH.getPath(), null); db.execSQL("PRAGMA key = 'otherkey'"); @@ -331,11 +313,11 @@ } catch ( SQLiteDatabaseCorruptException e ){ res = "encrypted"; } finally { db.close(); } - test_result("see_test_1.5", res, "encrypted", t4); + test_result("see_test_1.5", res, "encrypted"); } class MyHelper extends SQLiteOpenHelper { public MyHelper(Context ctx){ super(ctx, DB_PATH.getPath(), null, 1); } @@ -351,77 +333,52 @@ /* ** Check that SQLiteOpenHelper works. */ public void helper_test_1() throws Exception { - final long t0 = System.nanoTime(); SQLiteDatabase.deleteDatabase(DB_PATH); MyHelper helper = new MyHelper(this); SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL("INSERT INTO t1 VALUES ('x'), ('y'), ('z')"); String res = string_from_t1_x(db); - test_result("helper.1", res, ".x.y.z", t0); + test_result("helper.1", res, ".x.y.z"); helper.close(); } /* ** If this is a SEE build, check that SQLiteOpenHelper still works. */ public void see_test_2() throws Exception { - final long t0 = System.nanoTime(); if( !SQLiteDatabase.hasCodec() ) return; SQLiteDatabase.deleteDatabase(DB_PATH); MyHelper helper = new MyHelper(this); SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL("INSERT INTO t1 VALUES ('x'), ('y'), ('z')"); String res = string_from_t1_x(db); - test_result("see_test_2.1", res, ".x.y.z", t0); - final long t1 = System.nanoTime(); - test_result("see_test_2.2", db_is_encrypted(), "encrypted", t1); - final long t2 = System.nanoTime(); + test_result("see_test_2.1", res, ".x.y.z"); + test_result("see_test_2.2", db_is_encrypted(), "encrypted"); helper.close(); helper = new MyHelper(this); db = helper.getReadableDatabase(); - test_result("see_test_2.3", res, ".x.y.z", t2); - final long t3 = System.nanoTime(); + test_result("see_test_2.3", res, ".x.y.z"); db = helper.getWritableDatabase(); - test_result("see_test_2.4", res, ".x.y.z", t3); - final long t4 = System.nanoTime(); - - test_result("see_test_2.5", db_is_encrypted(), "encrypted", t4); - db.close(); - } - - private static boolean mLibIsLoaded = false; - private static void loadLibrary() { - if (!mLibIsLoaded) { - System.loadLibrary("sqliteX"); - mLibIsLoaded = true; - } + test_result("see_test_2.4", res, ".x.y.z"); + + test_result("see_test_2.5", db_is_encrypted(), "encrypted"); } public void run_the_tests(View view){ - myTV.setText(""); - view.post(new Runnable() { - @Override - public void run() { - run_the_tests_really(); - } - }); - } - - public void run_the_tests_really(){ - loadLibrary(); + System.loadLibrary("sqliteX"); DB_PATH = getApplicationContext().getDatabasePath("test.db"); - DB_PATH.mkdirs(); + DB_PATH.getParentFile().mkdirs(); myTV.setText(""); myNErr = 0; myNTest = 0; @@ -434,68 +391,13 @@ thread_test_1(); thread_test_2(); see_test_1(); see_test_2(); stmt_jrnl_test_1(); - json_test_1(); myTV.append("\n" + myNErr + " errors from " + myNTest + " tests\n"); } catch(Exception e) { myTV.append("Exception: " + e.toString() + "\n"); myTV.append(android.util.Log.getStackTraceString(e) + "\n"); } } - - public void json_test_1() throws Exception { - SQLiteDatabase.deleteDatabase(DB_PATH); - SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(DB_PATH, null); - final long t0 = System.nanoTime(); - db.beginTransaction(); - String res = ""; - - db.execSQL("CREATE TABLE t1(x, y)"); - JSONObject json = new JSONObject(); - json.put("Foo", 1); - json.put("Bar", "Gum"); - db.execSQL("INSERT INTO t1 VALUES (json('" + json.toString() + "'), 1)"); - final String r1 = json.toString(); - json.put("Foo", 2); - json.put("Bar", "Goo"); - final String r2 = json.toString(); - db.execSQL("INSERT INTO t1 VALUES (json('" + json.toString() + "'), 2)"); - json.put("Foo", 11); - json.put("Bar", "Zoo"); - db.execSQL("INSERT INTO t1 VALUES (json('" + json.toString() + "'), 11)"); - - SQLiteStatement s = db.compileStatement("Select json_extract(x, '$.Foo') from t1 where y = 1"); - res = s.simpleQueryForString(); - db.setTransactionSuccessful(); - db.endTransaction(); - test_result("json_test_1.1", res, "1", t0); - - db.beginTransaction(); - final long t1 = System.nanoTime(); - s.close(); - - s = db.compileStatement("Select json_extract(x, '$.Bar') from t1 where y = 1"); - res = s.simpleQueryForString(); - db.setTransactionSuccessful(); - db.endTransaction(); - test_result("json_test_1.2", res, "Gum", t1); - db.beginTransaction(); - final long t2 = System.nanoTime(); - s.close(); - - db.execSQL("Create Unique Index t1_foo on t1(json_extract(x, '$.Foo'))"); - db.execSQL("Create Unique Index t1_bar on t1(json_extract(x, '$.Bar'))"); - - s = db.compileStatement("Select x from t1 where json_extract(x, '$.Foo') > 1 order by json_extract(x, '$.Foo') limit 1"); - res = s.simpleQueryForString(); - db.setTransactionSuccessful(); - db.endTransaction(); - test_result("json_test_1.3", res, r2, t2); - - s.close(); - - db.close(); - } } DELETED src/org/sqlite/os/CancellationSignal.java Index: src/org/sqlite/os/CancellationSignal.java ================================================================== --- src/org/sqlite/os/CancellationSignal.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -** Modified to support SQLite extensions by the SQLite developers: -** sqlite-dev@sqlite.org. -*/ - -package org.sqlite.os; - -import org.sqlite.os.ICancellationSignal; -import android.os.RemoteException; - -/** - * Provides the ability to cancel an operation in progress. - */ -public final class CancellationSignal { - private boolean mIsCanceled; - private OnCancelListener mOnCancelListener; - private ICancellationSignal mRemote; - private boolean mCancelInProgress; - - /** - * Creates a cancellation signal, initially not canceled. - */ - public CancellationSignal() { - } - - /** - * Returns true if the operation has been canceled. - * - * @return True if the operation has been canceled. - */ - public boolean isCanceled() { - synchronized (this) { - return mIsCanceled; - } - } - - /** - * Throws {@link OperationCanceledException} if the operation has been canceled. - * - * @throws OperationCanceledException if the operation has been canceled. - */ - public void throwIfCanceled() { - if (isCanceled()) { - throw new OperationCanceledException(); - } - } - - /** - * Cancels the operation and signals the cancellation listener. - * If the operation has not yet started, then it will be canceled as soon as it does. - */ - public void cancel() { - final OnCancelListener listener; - final ICancellationSignal remote; - synchronized (this) { - if (mIsCanceled) { - return; - } - mIsCanceled = true; - mCancelInProgress = true; - listener = mOnCancelListener; - remote = mRemote; - } - - try { - if (listener != null) { - listener.onCancel(); - } - if (remote != null) { - try { - remote.cancel(); - } catch (RemoteException ex) { - } - } - } finally { - synchronized (this) { - mCancelInProgress = false; - notifyAll(); - } - } - } - - /** - * Sets the cancellation listener to be called when canceled. - * - * This method is intended to be used by the recipient of a cancellation signal - * such as a database or a content provider to handle cancellation requests - * while performing a long-running operation. This method is not intended to be - * used by applications themselves. - * - * If {@link CancellationSignal#cancel} has already been called, then the provided - * listener is invoked immediately. - * - * This method is guaranteed that the listener will not be called after it - * has been removed. - * - * @param listener The cancellation listener, or null to remove the current listener. - */ - public void setOnCancelListener(OnCancelListener listener) { - synchronized (this) { - waitForCancelFinishedLocked(); - - if (mOnCancelListener == listener) { - return; - } - mOnCancelListener = listener; - if (!mIsCanceled || listener == null) { - return; - } - } - listener.onCancel(); - } - - /** - * Sets the remote transport. - * - * If {@link CancellationSignal#cancel} has already been called, then the provided - * remote transport is canceled immediately. - * - * This method is guaranteed that the remote transport will not be called after it - * has been removed. - * - * @param remote The remote transport, or null to remove. - * - * @hide - */ - public void setRemote(ICancellationSignal remote) { - synchronized (this) { - waitForCancelFinishedLocked(); - - if (mRemote == remote) { - return; - } - mRemote = remote; - if (!mIsCanceled || remote == null) { - return; - } - } - try { - remote.cancel(); - } catch (RemoteException ex) { - } - } - - private void waitForCancelFinishedLocked() { - while (mCancelInProgress) { - try { - wait(); - } catch (InterruptedException ex) { - } - } - } - - /** - * Creates a transport that can be returned back to the caller of - * a Binder function and subsequently used to dispatch a cancellation signal. - * - * @return The new cancellation signal transport. - * - * @hide - */ - public static ICancellationSignal createTransport() { - return new Transport(); - } - - /** - * Given a locally created transport, returns its associated cancellation signal. - * - * @param transport The locally created transport, or null if none. - * @return The associated cancellation signal, or null if none. - * - * @hide - */ - public static CancellationSignal fromTransport(ICancellationSignal transport) { - if (transport instanceof Transport) { - return ((Transport)transport).mCancellationSignal; - } - return null; - } - - /** - * Listens for cancellation. - */ - public interface OnCancelListener { - /** - * Called when {@link CancellationSignal#cancel} is invoked. - */ - void onCancel(); - } - - private static final class Transport extends ICancellationSignal.Stub { - final CancellationSignal mCancellationSignal = new CancellationSignal(); - - @Override - public void cancel() throws RemoteException { - mCancellationSignal.cancel(); - } - } -} DELETED src/org/sqlite/os/ICancellationSignal.aidl Index: src/org/sqlite/os/ICancellationSignal.aidl ================================================================== --- src/org/sqlite/os/ICancellationSignal.aidl +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -** Modified to support SQLite extensions by the SQLite developers: -** sqlite-dev@sqlite.org. -*/ - -package org.sqlite.os; - -/** - * @hide - */ -interface ICancellationSignal { - oneway void cancel(); -} DELETED src/org/sqlite/os/OperationCanceledException.java Index: src/org/sqlite/os/OperationCanceledException.java ================================================================== --- src/org/sqlite/os/OperationCanceledException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -** Modified to support SQLite extensions by the SQLite developers: -** sqlite-dev@sqlite.org. -*/ - -package org.sqlite.os; - - -/** - * An exception type that is thrown when an operation in progress is canceled. - * - * @see CancellationSignal - */ -public class OperationCanceledException extends RuntimeException { - public OperationCanceledException() { - this(null); - } - - public OperationCanceledException(String message) { - super(message != null ? message : "The operation has been canceled."); - } -} Index: www/install.wiki ================================================================== --- www/install.wiki +++ www/install.wiki @@ -47,14 +47,18 @@ Android Studio 2.1 the dependency may be created using the project structure dialog (select "File" -> "Project Structure...") or by adding code similar to the following to the application modules build.gradle file: dependencies { - // Change "sqlite3-release" to the name of the new module! - compile project(':sqlite3-release') + // Change "sqlite-android-3130000" to the name of the new module! + compile project(':sqlite-android-3130000') } + +

    A more detailed description of using the steps above to create a very + simple applictation is [./verysimpleapp.wiki | available here]. +

    At time of writing, aar files may only be used directly in Android Studio projects, not projects created using other IDEs (e.g. Eclipse, IntelliJ IDEA). However, an aar is just a zip archive containing a classes.jar file that in turn contains the SQLite Android @@ -104,11 +108,11 @@ sqlite3/src/main/ directory of the project directory and run the ndk-build command. For example, on Linux if Android Studio and the NDK are installed using their default paths: $ cd sqlite3/src/main - $ ~/Android/Sdks/ndk-bundle/ndk-build + $ ~/Android/Sdk/ndk-bundle/ndk-build

    On modern hardware, this command takes roughly 2 minutes to build the native libraries for all Android architectures.

    The latest release of the public domain SQLite library comes bundled with the SQLite Android bindings code downloaded in step 1. If you wish @@ -127,17 +131,17 @@ the Android.mk file at this location: sqlite3/src/main/jni/sqlite/Android.mk

    - If the Android.mk or sqlite3.&lsp;ch&rsp; files + If the Android.mk or sqlite3.[ch] files are edited after ndk-build is run, it may be necessary to run the ndk-build clean command before rerunning ndk-build to ensure a correct build.

    Once ndk-build has been run successfully, unless you modify - the Android.mk or sqlite3.&lsp;ch&rsp; files, + the Android.mk or sqlite3.[ch] files, it should not be necessary to run it again. It does not have to be run each time the application is rebuilt.

  • Assemble the aar file. To assemble the aar file using the command line, first set environment variable ANDROID_HOME to the SDK @@ -156,11 +160,11 @@ causes the aar file to be created at: sqlite3/build/outputs/aar/sqlite3-release.aar.

    Once the custom aar file has been created, it may be used in an Android Studio application as described above. The aar file should be roughly - 3MB in size. If it is much smaller than this (closer to 100KB), this + 4.5MB in size. If it is much smaller than this (closer to 100KB), this indicates that the aar file is missing the native libraries. The usual cause of this is an unnoticed error while building the native libraries (step 2 above). ADDED www/verysimpleapp.wiki Index: www/verysimpleapp.wiki ================================================================== --- /dev/null +++ www/verysimpleapp.wiki @@ -0,0 +1,57 @@ + +

    Very Simple App

    + +

    +1. Create a new project in Android Studio. Use the "Basic Activity" template. +Leave all other settings at their defaults. + +

    + + +

    + + +
    + +

    +2. Modify the code in MainActivity.java as follows: + +

    + +
    + +

    +3. Set the name of the TextView widget in MainActivity to "tv_widget". + +

    + +
    + +

    +4. Import the pre-built SQLite aar file: + +

    + + +

    + +
    + +

    +5. Add the dependency on the new module to the application module: + +

    + + +

    + +
    + +

    +6. The very simple app is now ready to build! Click the green triangle on the +toolbar to build, deploy and run it. + +

    + +
    + ADDED www/vsa/1adddep.png Index: www/vsa/1adddep.png ================================================================== --- /dev/null +++ www/vsa/1adddep.png cannot compute difference between binary files ADDED www/vsa/1build.png Index: www/vsa/1build.png ================================================================== --- /dev/null +++ www/vsa/1build.png cannot compute difference between binary files ADDED www/vsa/1editmainactivity.png Index: www/vsa/1editmainactivity.png ================================================================== --- /dev/null +++ www/vsa/1editmainactivity.png cannot compute difference between binary files ADDED www/vsa/1importmodule.png Index: www/vsa/1importmodule.png ================================================================== --- /dev/null +++ www/vsa/1importmodule.png cannot compute difference between binary files ADDED www/vsa/1newproject.png Index: www/vsa/1newproject.png ================================================================== --- /dev/null +++ www/vsa/1newproject.png cannot compute difference between binary files ADDED www/vsa/1setwidgetid.png Index: www/vsa/1setwidgetid.png ================================================================== --- /dev/null +++ www/vsa/1setwidgetid.png cannot compute difference between binary files ADDED www/vsa/2adddep.png Index: www/vsa/2adddep.png ================================================================== --- /dev/null +++ www/vsa/2adddep.png cannot compute difference between binary files ADDED www/vsa/2importmodule.png Index: www/vsa/2importmodule.png ================================================================== --- /dev/null +++ www/vsa/2importmodule.png cannot compute difference between binary files ADDED www/vsa/2newproject.png Index: www/vsa/2newproject.png ================================================================== --- /dev/null +++ www/vsa/2newproject.png cannot compute difference between binary files ADDED www/vsa/3adddep.png Index: www/vsa/3adddep.png ================================================================== --- /dev/null +++ www/vsa/3adddep.png cannot compute difference between binary files ADDED www/vsa/3importmodule.png Index: www/vsa/3importmodule.png ================================================================== --- /dev/null +++ www/vsa/3importmodule.png cannot compute difference between binary files ADDED www/vsa/3newproject.png Index: www/vsa/3newproject.png ================================================================== --- /dev/null +++ www/vsa/3newproject.png cannot compute difference between binary files ADDED www/vsa/4newproject.png Index: www/vsa/4newproject.png ================================================================== --- /dev/null +++ www/vsa/4newproject.png cannot compute difference between binary files