From 6836fbb5db8464f56e682989996b2210b14231d0 Mon Sep 17 00:00:00 2001 From: SomeDude Date: Thu, 22 May 2008 19:33:00 +0200 Subject: [PATCH] version 0.2.17 --- include/freenet/iindexinserter.h | 1 + include/freenet/introductionpuzzleinserter.h | 22 +- include/global.h | 3 +- libs/sqlite3/sqlite3.c | 7638 +++++++++++++++++--------- libs/sqlite3/sqlite3.h | 345 +- libs/sqlite3/sqlite3ext.h | 14 +- readme.txt | 7 +- src/freenet/introductionpuzzleinserter.cpp | 182 +- src/freenet/messageinserter.cpp | 5 +- src/freenet/messagelistinserter.cpp | 98 +- src/freenet/trustlistinserter.cpp | 41 +- src/global.cpp | 88 +- src/http/pages/localidentitiespage.cpp | 25 +- src/http/pages/peertrustpage.cpp | 17 +- src/message.cpp | 37 +- 15 files changed, 5667 insertions(+), 2856 deletions(-) diff --git a/include/freenet/iindexinserter.h b/include/freenet/iindexinserter.h index 0539b29..edcc86b 100644 --- a/include/freenet/iindexinserter.h +++ b/include/freenet/iindexinserter.h @@ -111,6 +111,7 @@ const bool IIndexInserter::HandleMessage(FCPMessage &message) StringFunctions::Split(message["Identifier"],"|",idparts); StringFunctions::Convert(idparts[1],id); RemoveFromInsertList(id); + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IIndexInserter::HandleMessage IdentifierCollision for "+m_fcpuniquename+" "+message["Identifier"]); return true; } } diff --git a/include/freenet/introductionpuzzleinserter.h b/include/freenet/introductionpuzzleinserter.h index af66a50..c83cb9f 100644 --- a/include/freenet/introductionpuzzleinserter.h +++ b/include/freenet/introductionpuzzleinserter.h @@ -1,33 +1,19 @@ #ifndef _introductionpuzzle_inserter_ #define _introductionpuzzle_inserter_ -#include "../idatabase.h" -#include "../ilogger.h" -#include "../datetime.h" -#include "ifreenetregistrable.h" -#include "ifcpconnected.h" -#include "ifcpmessagehandler.h" -#include "iperiodicprocessor.h" +#include "iindexinserter.h" -class IntroductionPuzzleInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger +//class IntroductionPuzzleInserter:public IFreenetRegistrable,public IFCPConnected,public IFCPMessageHandler,public IPeriodicProcessor,public IDatabase,public ILogger +class IntroductionPuzzleInserter:public IIndexInserter { public: IntroductionPuzzleInserter(); IntroductionPuzzleInserter(FCPv2 *fcp); - void FCPConnected(); - void FCPDisconnected(); - - const bool HandleMessage(FCPMessage &message); - - void Process(); - - void RegisterWithThread(FreenetMasterThread *thread); - private: void Initialize(); void CheckForNeededInsert(); - void StartInsert(const long localidentityid); + const bool StartInsert(const long &localidentityid); void GenerateCaptcha(std::string &encodeddata, std::string &solution); const bool HandlePutSuccessful(FCPMessage &message); const bool HandlePutFailed(FCPMessage &message); diff --git a/include/global.h b/include/global.h index 29af655..30ad90d 100644 --- a/include/global.h +++ b/include/global.h @@ -5,7 +5,7 @@ #include #include "pthreadwrapper/thread.h" -#define FMS_VERSION "0.2.16" +#define FMS_VERSION "0.2.17" // opens database and creates tables and initial inserts if necessary void SetupDB(); @@ -18,6 +18,7 @@ void ConvertDB0106To0107(); void ConvertDB0107To0108(); void ConvertDB0108To0109(); void ConvertDB0109To0110(); +void ConvertDB0110To0111(); // inserts default options into the database void SetupDefaultOptions(); // opens logfile and sets it up diff --git a/libs/sqlite3/sqlite3.c b/libs/sqlite3/sqlite3.c index c846057..9044ec5 100644 --- a/libs/sqlite3/sqlite3.c +++ b/libs/sqlite3/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.5.7. By combining all the individual C code files into this +** version 3.5.9. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a one translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -11,13 +11,13 @@ ** programs, you need this file and the "sqlite3.h" header file that defines ** the programming interface to the SQLite library. (If you do not have ** the "sqlite3.h" header file at hand, you will find a copy in the first -** 5413 lines past this header comment.) Additional code files may be +** 5638 lines past this header comment.) Additional code files may be ** needed if you want a wrapper to interface SQLite with your choice of ** programming language. The code for the "sqlite3" command-line shell ** is also in a separate file. This file contains only code for the core ** SQLite library. ** -** This amalgamation was generated on 2008-03-17 18:47:08 UTC. +** This amalgamation was generated on 2008-05-14 16:20:58 UTC. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 @@ -41,111 +41,19 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.673 2008/03/14 13:02:08 mlcreech Exp $ +** @(#) $Id: sqliteInt.h,v 1.704 2008/05/13 13:27:34 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* -** Include the configuration header output by 'configure' if it was run -** (otherwise we get an empty default). +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build */ -/************** Include config.h in the middle of sqliteInt.h ****************/ -/************** Begin file config.h ******************************************/ -/* -** 2008 March 6 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Default configuration header in case the 'configure' script is not used -** -** @(#) $Id: config.h,v 1.1 2008/03/06 07:36:18 mlcreech Exp $ -*/ -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -/* We do nothing here, since no assumptions are made by default */ - +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" #endif -/************** End of config.h **********************************************/ -/************** Continuing where we left off in sqliteInt.h ******************/ - -/* Needed for various definitions... */ -#define _GNU_SOURCE - -/* -** Include standard header files as necessary -*/ -#ifdef HAVE_STDINT_H -#include -#endif -#ifdef HAVE_INTTYPES_H -#include -#endif - -/* -** If possible, use the C99 intptr_t type to define an integral type of -** equivalent size to a pointer. (Technically it's >= sizeof(void *), but -** practically it's == sizeof(void *)). We fall back to an int if this type -** isn't defined. -*/ -#ifdef HAVE_INTPTR_T - typedef intptr_t sqlite3_intptr_t; -#else - typedef int sqlite3_intptr_t; -#endif - - -/* -** The macro unlikely() is a hint that surrounds a boolean -** expression that is usually false. Macro likely() surrounds -** a boolean expression that is usually true. GCC is able to -** use these hints to generate better code, sometimes. -*/ -#if defined(__GNUC__) && 0 -# define likely(X) __builtin_expect((X),1) -# define unlikely(X) __builtin_expect((X),0) -#else -# define likely(X) !!(X) -# define unlikely(X) !!(X) -#endif - - -/* -** These #defines should enable >2GB file support on Posix if the -** underlying operating system supports it. If the OS lacks -** large file support, or if the OS is windows, these should be no-ops. -** -** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any -** system #includes. Hence, this block of code must be the very first -** code in all source files. -** -** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch -** on the compiler command line. This is necessary if you are compiling -** on a recent machine (ex: RedHat 7.2) but you want your code to work -** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 -** without this option, LFS is enable. But LFS does not exist in the kernel -** in RedHat 6.0, so the code won't work. Hence, for maximum binary -** portability you should omit LFS. -** -** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. -*/ -#ifndef SQLITE_DISABLE_LFS -# define _LARGE_FILE 1 -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# define _LARGEFILE_SOURCE 1 -#endif - - /************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ /************** Begin file sqliteLimit.h *************************************/ /* @@ -162,7 +70,7 @@ ** ** This file defines various limits of what SQLite can process. ** -** @(#) $Id: sqliteLimit.h,v 1.6 2007/12/17 16:20:07 drh Exp $ +** @(#) $Id: sqliteLimit.h,v 1.8 2008/03/26 15:56:22 drh Exp $ */ /* @@ -199,18 +107,24 @@ /* ** The maximum length of a single SQL statement in bytes. -** A value of zero means there is no limit. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. */ #ifndef SQLITE_MAX_SQL_LENGTH -# define SQLITE_MAX_SQL_LENGTH 0 +# define SQLITE_MAX_SQL_LENGTH 1000000000 #endif /* ** The maximum depth of an expression tree. This is limited to ** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might ** want to place more severe limits on the complexity of an -** expression. A value of 0 (the default) means do not enforce -** any limitation on expression tree depth. +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. */ #ifndef SQLITE_MAX_EXPR_DEPTH # define SQLITE_MAX_EXPR_DEPTH 1000 @@ -255,11 +169,9 @@ #endif /* -** The maximum number of attached databases. This must be at least 2 -** in order to support the main database file (0) and the file used to -** hold temporary tables (1). And it must be less than 32 because -** we use a bitmask of databases with a u32 in places (for example -** the Parse.cookieMask field). +** The maximum number of attached databases. This must be between 0 +** and 30. The upper bound on 30 is because a 32-bit integer bitmap +** is used internally to track attached databases. */ #ifndef SQLITE_MAX_ATTACHED # define SQLITE_MAX_ATTACHED 10 @@ -331,46 +243,83 @@ /************** End of sqliteLimit.h *****************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicous pointer arithmetic */ +#endif + +/* Needed for various definitions... */ +#define _GNU_SOURCE + /* -** For testing purposes, the various size limit constants are really -** variables that we can modify in the testfixture. +** Include standard header files as necessary */ -#ifdef SQLITE_TEST - #undef SQLITE_MAX_LENGTH - #undef SQLITE_MAX_COLUMN - #undef SQLITE_MAX_SQL_LENGTH - #undef SQLITE_MAX_EXPR_DEPTH - #undef SQLITE_MAX_COMPOUND_SELECT - #undef SQLITE_MAX_VDBE_OP - #undef SQLITE_MAX_FUNCTION_ARG - #undef SQLITE_MAX_VARIABLE_NUMBER - #undef SQLITE_MAX_PAGE_SIZE - #undef SQLITE_MAX_PAGE_COUNT - #undef SQLITE_MAX_LIKE_PATTERN_LENGTH - - #define SQLITE_MAX_LENGTH sqlite3MAX_LENGTH - #define SQLITE_MAX_COLUMN sqlite3MAX_COLUMN - #define SQLITE_MAX_SQL_LENGTH sqlite3MAX_SQL_LENGTH - #define SQLITE_MAX_EXPR_DEPTH sqlite3MAX_EXPR_DEPTH - #define SQLITE_MAX_COMPOUND_SELECT sqlite3MAX_COMPOUND_SELECT - #define SQLITE_MAX_VDBE_OP sqlite3MAX_VDBE_OP - #define SQLITE_MAX_FUNCTION_ARG sqlite3MAX_FUNCTION_ARG - #define SQLITE_MAX_VARIABLE_NUMBER sqlite3MAX_VARIABLE_NUMBER - #define SQLITE_MAX_PAGE_SIZE sqlite3MAX_PAGE_SIZE - #define SQLITE_MAX_PAGE_COUNT sqlite3MAX_PAGE_COUNT - #define SQLITE_MAX_LIKE_PATTERN_LENGTH sqlite3MAX_LIKE_PATTERN_LENGTH - - extern int sqlite3MAX_LENGTH; - extern int sqlite3MAX_COLUMN; - extern int sqlite3MAX_SQL_LENGTH; - extern int sqlite3MAX_EXPR_DEPTH; - extern int sqlite3MAX_COMPOUND_SELECT; - extern int sqlite3MAX_VDBE_OP; - extern int sqlite3MAX_FUNCTION_ARG; - extern int sqlite3MAX_VARIABLE_NUMBER; - extern int sqlite3MAX_PAGE_SIZE; - extern int sqlite3MAX_PAGE_COUNT; - extern int sqlite3MAX_LIKE_PATTERN_LENGTH; +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +/* +** A macro used to aid in coverage testing. When doing coverage +** testing, the condition inside the argument must be evaluated +** both true and false in order to get full branch coverage. +** This macro can be inserted to ensure adequate test coverage +** in places where simple condition/decision coverage is inadequate. +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. GCC is able to +** use these hints to generate better code, sometimes. +*/ +#if defined(__GNUC__) && 0 +# define likely(X) __builtin_expect((X),1) +# define unlikely(X) __builtin_expect((X),0) +#else +# define likely(X) !!(X) +# define unlikely(X) !!(X) +#endif + + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 #endif @@ -487,7 +436,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.291 2008/03/08 12:37:31 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.312 2008/05/12 12:39:56 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -550,8 +499,8 @@ extern "C" { ** with the value (X*1000000 + Y*1000 + Z) where X, Y, and ** Z are the major version, minor version, and release number. */ -#define SQLITE_VERSION "3.5.7" -#define SQLITE_VERSION_NUMBER 3005007 +#define SQLITE_VERSION "3.5.9" +#define SQLITE_VERSION_NUMBER 3005009 /* ** CAPI3REF: Run-Time Library Version Numbers {F10020} @@ -612,7 +561,7 @@ SQLITE_API int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle {F12000} -** KEYWORDS: {database connection} +** KEYWORDS: {database connection} {database connections} ** ** Each open SQLite database is represented by pointer to an instance of the ** opaque structure named "sqlite3". It is useful to think of an sqlite3 @@ -2048,17 +1997,42 @@ SQLITE_API sqlite3_int64 sqlite3_memory_used(void); SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* +** CAPI3REF: Pseudo-Random Number Generator {F17390} +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random ROWIDs when inserting new records into a table that +** already uses the largest possible ROWID. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** appliations to access the same PRNG for other purposes. +** +** A call to this routine stores N bytes of randomness into buffer P. +** +** The first time this routine is invoked (either internally or by +** the application) the PRNG is seeded using randomness obtained +** from the xRandomness method of the default [sqlite3_vfs] object. +** On all subsequent invocations, the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +** +** INVARIANTS: +** +** {F17392} The [sqlite3_randomness(N,P)] interface writes N bytes of +** high-quality pseudo-randomness into buffer P. +*/ +SQLITE_API void sqlite3_randomness(int N, void *P); + +/* ** CAPI3REF: Compile-Time Authorization Callbacks {F12500} ** ** This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. +** [database connection], supplied in the first argument. ** The authorizer callback is invoked as SQL statements are being compiled ** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], ** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various ** points during the compilation process, as logic is being created ** to perform various actions, the authorizer callback is invoked to ** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the ** specific action but allow the SQL statement to continue to be ** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be ** rejected with an error. If the authorizer callback returns @@ -2071,9 +2045,9 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that ** access is denied. If the authorizer code is [SQLITE_READ] -** and the callback returns [SQLITE_IGNORE] then the prepared -** statement is constructed to insert a NULL value in place of -** the table column that would have +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have ** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] ** return can be used to deny an untrusted user access to individual ** columns of a table. @@ -2086,7 +2060,8 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** parameters to the callback are zero-terminated strings that contain ** additional details about the action to be authorized. ** -** An authorizer is used when preparing SQL statements from an untrusted +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted ** source, to ensure that the SQL statements do not try to access data ** that they are not allowed to see, or that they do not try to ** execute malicious statements that damage the database. For @@ -2094,8 +2069,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** SQL queries for evaluation by a database. But the application does ** not want the user to be able to make arbitrary changes to the ** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. ** ** Only a single authorizer can be in place on a database connection ** at a time. Each call to sqlite3_set_authorizer overrides the @@ -2410,6 +2390,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** The third options is behavior that is always used for [sqlite3_open()] ** and [sqlite3_open16()]. ** +** If the 3rd parameter to [sqlite3_open_v2()] is not one of the +** combinations shown above then the behavior is undefined. +** ** If the filename is ":memory:", then an private ** in-memory database is created for the connection. This in-memory ** database will vanish when the database connection is closed. Future @@ -2588,6 +2571,113 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3*); typedef struct sqlite3_stmt sqlite3_stmt; /* +** CAPI3REF: Run-time Limits {F12760} +** +** This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct. The function returns the old limit. +** +** If the new limit is a negative number, the limit is unchanged. +** For the limit category of SQLITE_LIMIT_XYZ there is a hard upper +** bound set by a compile-time C-preprocess macro named SQLITE_MAX_XYZ. +** (The "_LIMIT_" in the name is changed to "_MAX_".) +** Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper limit. +** +** Run time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** webbrowser that has its own databases for storing history and +** separate databases controlled by javascript applications downloaded +** off the internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attach. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** This interface is currently considered experimental and is subject +** to change or removal without prior notice. +** +** INVARIANTS: +** +** {F12762} A successful call to [sqlite3_limit(D,C,V)] where V is +** positive changes the +** limit on the size of construct C in [database connection] D +** to the lessor of V and the hard upper bound on the size +** of C that is set at compile-time. +** +** {F12766} A successful call to [sqlite3_limit(D,C,V)] where V is negative +** leaves the state of [database connection] D unchanged. +** +** {F12769} A successful call to [sqlite3_limit(D,C,V)] returns the +** value of the limit on the size of construct C in +** in [database connection] D as it was prior to the call. +*/ +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories {F12790} +** KEYWORDS: {limit category} {limit categories} +** +** These constants define various aspects of a [database connection] +** that can be limited in size by calls to [sqlite3_limit()]. +** The meanings of the various limits are as follows: +** +**
+**
SQLITE_LIMIT_LENGTH
+**
The maximum size of any +** string or blob or table row.
+** +**
SQLITE_LIMIT_SQL_LENGTH
+**
The maximum length of an SQL statement.
+** +**
SQLITE_LIMIT_COLUMN
+**
The maximum number of columns in a table definition or in the +** result set of a SELECT or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
+** +**
SQLITE_LIMIT_EXPR_DEPTH
+**
The maximum depth of the parse tree on any expression.
+** +**
SQLITE_LIMIT_COMPOUND_SELECT
+**
The maximum number of terms in a compound SELECT statement.
+** +**
SQLITE_LIMIT_VDBE_OP
+**
The maximum number of instructions in a virtual machine program +** used to implement an SQL statement.
+** +**
SQLITE_LIMIT_FUNCTION_ARG
+**
The maximum number of arguments on a function.
+** +**
SQLITE_LIMIT_ATTACHED
+**
The maximum number of attached databases.
+** +**
SQLITE_LIMIT_LIKE_PATTERN_LENGTH
+**
The maximum length of the pattern argument to the LIKE or +** GLOB operators.
+** +**
SQLITE_LIMIT_VARIABLE_NUMBER
+**
The maximum number of variables in an SQL statement that can +** be bound.
+**
+*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 + +/* ** CAPI3REF: Compiling An SQL Statement {F13010} ** ** To execute an SQL query, it must first be compiled into a byte-code @@ -2606,7 +2696,11 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** If nByte is non-negative, then it is the maximum number of ** bytes read from zSql. When nByte is non-negative, the ** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be had by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes.{END} ** ** *pzTail is made to point to the first byte past the end of the ** first SQL statement in zSql. These routines only compiles the first @@ -2672,7 +2766,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** read from zSql is read up to the first zero terminator. ** ** {F13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)] -** and its variants is non-negative, then nBytes bytes +** and its variants is non-negative, then at most nBytes bytes ** SQL text is read from zSql. ** ** {F13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants @@ -2751,12 +2845,39 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Dynamically Typed Value Object {F15000} +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} ** ** SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. +** that can be stored in a database table. ** SQLite uses dynamic typing for the values it stores. ** Values stored in sqlite3_value objects can be ** be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. A internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with SQLITE_THREADSAFE=0 and with [sqlite3_threadsafe()] returning 0) +** then there is no distinction between +** protected and unprotected sqlite3_value objects and they can be +** used interchangable. However, for maximum code portability it +** is recommended that applications make the distinction between +** between protected and unprotected sqlite3_value objects even if +** they are single threaded. +** +** The sqlite3_value objects that are passed as parameters into the +** implementation of application-defined SQL functions are protected. +** The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. All other +** interfaces that use sqlite3_value require protected sqlite3_value objects. */ typedef struct Mem sqlite3_value; @@ -2808,8 +2929,7 @@ typedef struct sqlite3_context sqlite3_context; ** In those ** routines that have a fourth argument, its value is the number of bytes ** in the parameter. To be clear: the value is the number of bytes -** in the value, not the number of characters. The number -** of bytes does not include the zero-terminator at the end of strings. +** in the value, not the number of characters. ** If the fourth parameter is negative, the length of the string is ** number of bytes up to the first zero terminator. ** @@ -2918,6 +3038,10 @@ typedef struct sqlite3_context sqlite3_context; ** ** {F13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound ** is a blob of L bytes, or a zero-length blob if L is negative. +** +** {F13551} In calls to [sqlite3_bind_value(S,N,V)] the V argument may +** be either a [protected sqlite3_value] object or an +** [unprotected sqlite3_value] object. */ SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); @@ -2961,11 +3085,12 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); ** ** This routine returns a pointer to the name of the n-th ** SQL parameter in a [prepared statement]. -** SQL parameters of the form ":AAA" or "@AAA" or "$AAA" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" +** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" ** is included as part of the name. -** Parameters of the form "?" or "?NNN" have no name. +** Parameters of the form "?" without a following integer have no name. ** ** The first host parameter has an index of 1, not 0. ** @@ -2985,8 +3110,7 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); ** a UTF-8 rendering of the name of the SQL parameter in ** [prepared statement] S having index N, or ** NULL if there is no SQL parameter with index N or if the -** parameter with index N is an anonymous parameter "?" or -** a numbered parameter "?NNN". +** parameter with index N is an anonymous parameter "?". */ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); @@ -3283,7 +3407,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** new "v2" interface is recommended for new applications but the legacy ** interface will continue to be supported. ** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], +** In the legacy interface, the return value will be either [SQLITE_BUSY], ** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. ** With the "v2" interface, any of the other [SQLITE_OK | result code] ** or [SQLITE_IOERR_READ | extended result code] might be returned as @@ -3476,6 +3600,15 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** but leaves the result in UTF-16 in native byte order instead of UTF-8. ** The zero terminator is not included in this count. ** +** The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like +** [sqlite3_value_int()], [sqlite3_value_text()], or [sqlite3_value_bytes()], +** then the behavior is undefined. +** ** These routines attempt to convert the value where appropriate. For ** example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to do the conversion @@ -3617,7 +3750,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [prepared statement] S. ** ** {F13830} The [sqlite3_column_value(S,N)] interface returns a -** pointer to the [sqlite3_value] object that for the +** pointer to an [unprotected sqlite3_value] object for the ** Nth column in the current row of the result set for ** [prepared statement] S. */ @@ -3807,6 +3940,12 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); ** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finializer ** function L will always be invoked exactly once if the ** step function S is called one or more times. +** +** {F16142} When SQLite invokes either the xFunc or xStep function of +** an application-defined SQL function or aggregate created +** by [sqlite3_create_function()] or [sqlite3_create_function16()], +** then the array of [sqlite3_value] objects passed as the +** third parameter are always [protected sqlite3_value] objects. */ SQLITE_API int sqlite3_create_function( sqlite3 *db, @@ -3869,14 +4008,18 @@ SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlit ** to [sqlite3_create_function()] and [sqlite3_create_function16()] ** define callbacks that implement the SQL functions and aggregates. ** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for +** [protected sqlite3_value] objects. There is one [sqlite3_value] object for ** each parameter to the SQL function. These routines are used to ** extract values from the [sqlite3_value] objects. ** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** ** These routines work just like the corresponding ** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. +** these routines take a single [protected sqlite3_value] object pointer +** instead of an [sqlite3_stmt*] pointer and an integer column number. ** ** The sqlite3_value_text16() interface extracts a UTF16 string ** in the native byte-order of the host machine. The @@ -3898,16 +4041,13 @@ SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlit ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. +** the SQL function that supplied the [sqlite3_value*] parameters. ** ** ** INVARIANTS: ** ** {F15103} The [sqlite3_value_blob(V)] interface converts the -** [sqlite3_value] object V into a blob and then returns a +** [protected sqlite3_value] object V into a blob and then returns a ** pointer to the converted value. ** ** {F15106} The [sqlite3_value_bytes(V)] interface returns the @@ -3923,33 +4063,33 @@ SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlit ** [sqlite3_value_text16be(V)], or [sqlite3_value_text16le(V)]. ** ** {F15112} The [sqlite3_value_double(V)] interface converts the -** [sqlite3_value] object V into a floating point value and +** [protected sqlite3_value] object V into a floating point value and ** returns a copy of that value. ** ** {F15115} The [sqlite3_value_int(V)] interface converts the -** [sqlite3_value] object V into a 64-bit signed integer and +** [protected sqlite3_value] object V into a 64-bit signed integer and ** returns the lower 32 bits of that integer. ** ** {F15118} The [sqlite3_value_int64(V)] interface converts the -** [sqlite3_value] object V into a 64-bit signed integer and +** [protected sqlite3_value] object V into a 64-bit signed integer and ** returns a copy of that integer. ** ** {F15121} The [sqlite3_value_text(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated UTF-8 +** [protected sqlite3_value] object V into a zero-terminated UTF-8 ** string and returns a pointer to that string. ** ** {F15124} The [sqlite3_value_text16(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated 2-byte +** [protected sqlite3_value] object V into a zero-terminated 2-byte ** aligned UTF-16 native byte order ** string and returns a pointer to that string. ** ** {F15127} The [sqlite3_value_text16be(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated 2-byte +** [protected sqlite3_value] object V into a zero-terminated 2-byte ** aligned UTF-16 big-endian ** string and returns a pointer to that string. ** ** {F15130} The [sqlite3_value_text16le(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated 2-byte +** [protected sqlite3_value] object V into a zero-terminated 2-byte ** aligned UTF-16 little-endian ** string and returns a pointer to that string. ** @@ -3959,12 +4099,12 @@ SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlit ** the [sqlite3_value] object V. ** ** {F15136} The [sqlite3_value_numeric_type(V)] interface converts -** the [sqlite3_value] object V into either an integer or +** the [protected sqlite3_value] object V into either an integer or ** a floating point value if it can do so without loss of ** information, and returns one of [SQLITE_NULL], ** [SQLITE_INTEGER], [SQLITE_FLOAT], [SQLITE_TEXT], or ** [SQLITE_BLOB] as appropriate for -** the [sqlite3_value] object V after the conversion attempt. +** the [protected sqlite3_value] object V after the conversion attempt. */ SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); SQLITE_API int sqlite3_value_bytes(sqlite3_value*); @@ -4049,6 +4189,25 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); SQLITE_API void *sqlite3_user_data(sqlite3_context*); /* +** CAPI3REF: Database Connection For Functions {F16250} +** +** The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** INVARIANTS: +** +** {F16253} The [sqlite3_context_db_handle(C)] interface returns a copy of the +** D pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)] +** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that +** registered the SQL function associated with +** [sqlite3_context] C. +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* ** CAPI3REF: Function Auxiliary Data {F16270} ** ** The following two functions may be used by scalar SQL functions to @@ -4187,7 +4346,8 @@ typedef void (*sqlite3_destructor_type)(void*); ** modify the text after they return without harm. ** The sqlite3_result_error_code() function changes the error code ** returned by SQLite as a result of an error in a function. By default, -** the error code is SQLITE_ERROR. +** the error code is SQLITE_ERROR. A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. ** ** The sqlite3_result_toobig() interface causes SQLite ** to throw an error indicating that a string or BLOB is to long @@ -4234,11 +4394,14 @@ typedef void (*sqlite3_destructor_type)(void*); ** from [sqlite3_malloc()] before it returns. ** ** The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. The +** the application-defined function to be a copy the +** [unprotected sqlite3_value] object specified by the 2nd parameter. The ** sqlite3_result_value() interface makes a copy of the [sqlite3_value] ** so that [sqlite3_value] specified in the parameter may change or ** be deallocated after sqlite3_result_value() returns without harm. +** A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. ** ** If these routines are called from within the different thread ** than the one containing the application-defined function that recieved @@ -4289,26 +4452,27 @@ typedef void (*sqlite3_destructor_type)(void*); ** ** {F16436} The [sqlite3_result_text(C,V,N,D)] interface changes the ** return value of function C to be the UTF8 string -** V up through the first zero or until N bytes are read if N -** is positive. +** V up to the first zero if N is negative +** or the first N bytes of V if N is non-negative. ** ** {F16439} The [sqlite3_result_text16(C,V,N,D)] interface changes the ** return value of function C to be the UTF16 native byte order -** string V up through the first zero or until N bytes are read if N -** is positive. +** string V up to the first zero if N is +** negative or the first N bytes of V if N is non-negative. ** ** {F16442} The [sqlite3_result_text16be(C,V,N,D)] interface changes the ** return value of function C to be the UTF16 big-endian -** string V up through the first zero or until N bytes are read if N -** is positive. +** string V up to the first zero if N is +** is negative or the first N bytes or V if N is non-negative. ** ** {F16445} The [sqlite3_result_text16le(C,V,N,D)] interface changes the ** return value of function C to be the UTF16 little-endian -** string V up through the first zero or until N bytes are read if N -** is positive. +** string V up to the first zero if N is +** negative or the first N bytes of V if N is non-negative. ** ** {F16448} The [sqlite3_result_value(C,V)] interface changes the -** return value of function C to be [sqlite3_value] object V. +** return value of function C to be [unprotected sqlite3_value] +** object V. ** ** {F16451} The [sqlite3_result_zeroblob(C,N)] interface changes the ** return value of function C to be an N-byte blob of all zeros. @@ -5368,7 +5532,7 @@ typedef struct sqlite3_blob sqlite3_blob; ** CAPI3REF: Open A BLOB For Incremental I/O {F17810} ** ** This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; +** in row iRow, column zColumn, table zTable in database zDb; ** in other words, the same blob that would be selected by: ** **
@@ -5379,6 +5543,12 @@ typedef struct sqlite3_blob sqlite3_blob;
 ** read and write access. If it is zero, the blob is opened for read 
 ** access.
 **
+** Note that the database name is not the filename that contains
+** the database but rather the symbolic name of the database that
+** is assigned when the database is connected using [ATTACH].
+** For the main database file, the database name is "main".  For
+** TEMP tables, the database name is "temp".
+**
 ** On success, [SQLITE_OK] is returned and the new 
 ** [sqlite3_blob | blob handle] is written to *ppBlob. 
 ** Otherwise an error code is returned and 
@@ -5507,10 +5677,11 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
 **          the [sqlite3_blob_read(P,Z,N,X)] interface returns an
 **          appropriate [error code] or [extended error code].
 **
-** {F17868} If an error occurs during evaluation of [sqlite3_blob_read(D,...)]
+** {F17868} If an error occurs during evaluation of [sqlite3_blob_read(P,...)]
 **          then subsequent calls to [sqlite3_errcode(D)],
 **          [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] will return
-**          information approprate for that error.
+**          information approprate for that error, where D is the
+**          database handle that was used to open blob handle P.
 */
 SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
 
@@ -5678,6 +5849,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
 ** 
  • SQLITE_MUTEX_STATIC_MEM2 **
  • SQLITE_MUTEX_STATIC_PRNG **
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_LRU2 ** {END} ** ** {F17015} The first two constants cause sqlite3_mutex_alloc() to create @@ -5790,6 +5962,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); #define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */ /* ** CAPI3REF: Low-Level Control Of Database Files {F11300} @@ -5851,9 +6024,10 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_FAULT_FAILURES 2 #define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES 3 #define SQLITE_TESTCTRL_FAULT_PENDING 4 - - - +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 /* @@ -6149,8 +6323,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #include #include -#define sqlite3_isnan(X) ((X)!=(X)) - /* ** If compiling for a processor that lacks floating point support, ** substitute integer for floating-point @@ -6304,6 +6476,14 @@ SQLITE_PRIVATE const int sqlite3one; #endif /* +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +/* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** @@ -6398,7 +6578,7 @@ typedef struct WhereLevel WhereLevel; ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.94 2007/12/07 18:55:28 drh Exp $ +** @(#) $Id: btree.h,v 1.98 2008/04/26 13:39:47 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -6512,17 +6692,26 @@ SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); +struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */ + SQLITE_PRIVATE int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ - int(*)(void*,int,const void*,int,const void*), /* Key comparison function */ - void*, /* First argument to compare function */ - BtCursor **ppCursor /* Returned cursor */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ ); +SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); -SQLITE_PRIVATE int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); +SQLITE_PRIVATE int sqlite3BtreeMoveto( + BtCursor*, + const void *pKey, + struct UnpackedRecord *pUnKey, + i64 nKey, + int bias, + int *pRes +); SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, @@ -6608,7 +6797,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.125 2008/01/17 17:27:31 drh Exp $ +** $Id: vdbe.h,v 1.131 2008/05/01 17:03:49 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -6626,6 +6815,7 @@ typedef struct Vdbe Vdbe; */ typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; +typedef struct UnpackedRecord UnpackedRecord; /* ** A single instruction of the virtual machine has an opcode @@ -6635,7 +6825,7 @@ typedef struct Mem Mem; struct VdbeOp { u8 opcode; /* What operation to perform */ signed char p4type; /* One of the P4_xxx constants for p4 */ - u8 flags; /* Flags for internal use */ + u8 opflags; /* Not currently used */ u8 p5; /* Fifth parameter is an unsigned character */ int p1; /* First operand */ int p2; /* Second parameter (often the jump destination) */ @@ -6711,7 +6901,15 @@ typedef struct VdbeOpList VdbeOpList; #define COLNAME_DATABASE 2 #define COLNAME_TABLE 3 #define COLNAME_COLUMN 4 -#define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#else +# ifdef SQLITE_OMIT_DECLTYPE +# define COLNAME_N 1 /* Store only the name */ +# else +# define COLNAME_N 2 /* Store the name and decltype */ +# endif +#endif /* ** The following macro converts a relative address in the p2 field @@ -6730,137 +6928,137 @@ typedef struct VdbeOpList VdbeOpList; /* Automatically generated. Do not edit */ /* See the mkopcodeh.awk script for details */ #define OP_VNext 1 -#define OP_Column 2 -#define OP_SetCookie 3 +#define OP_Affinity 2 +#define OP_Column 3 +#define OP_SetCookie 4 #define OP_Real 125 /* same as TK_FLOAT */ -#define OP_Sequence 4 -#define OP_MoveGt 5 +#define OP_Sequence 5 +#define OP_MoveGt 6 #define OP_Ge 72 /* same as TK_GE */ -#define OP_RowKey 6 -#define OP_SCopy 7 +#define OP_RowKey 7 +#define OP_SCopy 8 #define OP_Eq 68 /* same as TK_EQ */ -#define OP_OpenWrite 8 +#define OP_OpenWrite 9 #define OP_NotNull 66 /* same as TK_NOTNULL */ -#define OP_If 9 +#define OP_If 10 #define OP_ToInt 141 /* same as TK_TO_INT */ #define OP_String8 88 /* same as TK_STRING */ -#define OP_VRowid 10 -#define OP_CollSeq 11 -#define OP_OpenRead 12 -#define OP_Expire 13 -#define OP_AutoCommit 14 +#define OP_VRowid 11 +#define OP_CollSeq 12 +#define OP_OpenRead 13 +#define OP_Expire 14 +#define OP_AutoCommit 15 #define OP_Gt 69 /* same as TK_GT */ -#define OP_IntegrityCk 15 -#define OP_Sort 17 -#define OP_Copy 18 -#define OP_Trace 19 -#define OP_Function 20 -#define OP_IfNeg 21 +#define OP_IntegrityCk 17 +#define OP_Sort 18 +#define OP_Copy 19 +#define OP_Trace 20 +#define OP_Function 21 +#define OP_IfNeg 22 #define OP_And 61 /* same as TK_AND */ #define OP_Subtract 79 /* same as TK_MINUS */ -#define OP_Noop 22 -#define OP_Return 23 +#define OP_Noop 23 +#define OP_Return 24 #define OP_Remainder 82 /* same as TK_REM */ -#define OP_NewRowid 24 +#define OP_NewRowid 25 #define OP_Multiply 80 /* same as TK_STAR */ -#define OP_Variable 25 -#define OP_String 26 -#define OP_RealAffinity 27 -#define OP_VRename 28 -#define OP_ParseSchema 29 -#define OP_VOpen 30 -#define OP_Close 31 -#define OP_CreateIndex 32 -#define OP_IsUnique 33 -#define OP_NotFound 34 -#define OP_Int64 35 -#define OP_MustBeInt 36 -#define OP_Halt 37 -#define OP_Rowid 38 -#define OP_IdxLT 39 -#define OP_AddImm 40 -#define OP_Statement 41 -#define OP_RowData 42 -#define OP_MemMax 43 +#define OP_Variable 26 +#define OP_String 27 +#define OP_RealAffinity 28 +#define OP_VRename 29 +#define OP_ParseSchema 30 +#define OP_VOpen 31 +#define OP_Close 32 +#define OP_CreateIndex 33 +#define OP_IsUnique 34 +#define OP_NotFound 35 +#define OP_Int64 36 +#define OP_MustBeInt 37 +#define OP_Halt 38 +#define OP_Rowid 39 +#define OP_IdxLT 40 +#define OP_AddImm 41 +#define OP_Statement 42 +#define OP_RowData 43 +#define OP_MemMax 44 #define OP_Or 60 /* same as TK_OR */ -#define OP_NotExists 44 -#define OP_Gosub 45 +#define OP_NotExists 45 +#define OP_Gosub 46 #define OP_Divide 81 /* same as TK_SLASH */ -#define OP_Integer 46 +#define OP_Integer 47 #define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/ -#define OP_Prev 47 +#define OP_Prev 48 #define OP_Concat 83 /* same as TK_CONCAT */ #define OP_BitAnd 74 /* same as TK_BITAND */ -#define OP_VColumn 48 -#define OP_CreateTable 49 -#define OP_Last 50 +#define OP_VColumn 49 +#define OP_CreateTable 50 +#define OP_Last 51 #define OP_IsNull 65 /* same as TK_ISNULL */ -#define OP_IncrVacuum 51 -#define OP_IdxRowid 52 +#define OP_IncrVacuum 52 +#define OP_IdxRowid 53 #define OP_ShiftRight 77 /* same as TK_RSHIFT */ -#define OP_ResetCount 53 -#define OP_FifoWrite 54 -#define OP_ContextPush 55 -#define OP_DropTrigger 56 -#define OP_DropIndex 57 -#define OP_IdxGE 58 -#define OP_IdxDelete 59 -#define OP_Vacuum 62 -#define OP_MoveLe 63 -#define OP_IfNot 64 -#define OP_DropTable 73 -#define OP_MakeRecord 84 +#define OP_ResetCount 54 +#define OP_FifoWrite 55 +#define OP_ContextPush 56 +#define OP_DropTrigger 57 +#define OP_DropIndex 58 +#define OP_IdxGE 59 +#define OP_IdxDelete 62 +#define OP_Vacuum 63 +#define OP_MoveLe 64 +#define OP_IfNot 73 +#define OP_DropTable 84 +#define OP_MakeRecord 85 #define OP_ToBlob 139 /* same as TK_TO_BLOB */ -#define OP_ResultRow 85 -#define OP_Delete 86 -#define OP_AggFinal 89 +#define OP_ResultRow 86 +#define OP_Delete 89 +#define OP_AggFinal 90 #define OP_ShiftLeft 76 /* same as TK_LSHIFT */ -#define OP_Goto 90 -#define OP_TableLock 91 -#define OP_FifoRead 92 -#define OP_Clear 93 -#define OP_MoveLt 94 +#define OP_Goto 91 +#define OP_TableLock 92 +#define OP_FifoRead 93 +#define OP_Clear 94 +#define OP_MoveLt 95 #define OP_Le 70 /* same as TK_LE */ -#define OP_VerifyCookie 95 -#define OP_AggStep 96 +#define OP_VerifyCookie 96 +#define OP_AggStep 97 #define OP_ToText 138 /* same as TK_TO_TEXT */ #define OP_Not 16 /* same as TK_NOT */ #define OP_ToReal 142 /* same as TK_TO_REAL */ -#define OP_SetNumColumns 97 -#define OP_Transaction 98 -#define OP_VFilter 99 +#define OP_SetNumColumns 98 +#define OP_Transaction 99 +#define OP_VFilter 100 #define OP_Ne 67 /* same as TK_NE */ -#define OP_VDestroy 100 -#define OP_ContextPop 101 +#define OP_VDestroy 101 +#define OP_ContextPop 102 #define OP_BitOr 75 /* same as TK_BITOR */ -#define OP_Next 102 -#define OP_IdxInsert 103 +#define OP_Next 103 +#define OP_IdxInsert 104 #define OP_Lt 71 /* same as TK_LT */ -#define OP_Insert 104 -#define OP_Destroy 105 -#define OP_ReadCookie 106 -#define OP_ForceInt 107 -#define OP_LoadAnalysis 108 -#define OP_Explain 109 -#define OP_OpenPseudo 110 -#define OP_OpenEphemeral 111 -#define OP_Null 112 -#define OP_Move 113 -#define OP_Blob 114 +#define OP_Insert 105 +#define OP_Destroy 106 +#define OP_ReadCookie 107 +#define OP_ForceInt 108 +#define OP_LoadAnalysis 109 +#define OP_Explain 110 +#define OP_OpenPseudo 111 +#define OP_OpenEphemeral 112 +#define OP_Null 113 +#define OP_Move 114 +#define OP_Blob 115 #define OP_Add 78 /* same as TK_PLUS */ -#define OP_Rewind 115 -#define OP_MoveGe 116 -#define OP_VBegin 117 -#define OP_VUpdate 118 -#define OP_IfZero 119 +#define OP_Rewind 116 +#define OP_MoveGe 117 +#define OP_VBegin 118 +#define OP_VUpdate 119 +#define OP_IfZero 120 #define OP_BitNot 87 /* same as TK_BITNOT */ -#define OP_VCreate 120 -#define OP_Found 121 -#define OP_IfPos 122 -#define OP_NullRow 123 +#define OP_VCreate 121 +#define OP_Found 122 +#define OP_IfPos 123 +#define OP_NullRow 124 /* The following opcode values are never used */ -#define OP_NotUsed_124 124 #define OP_NotUsed_126 126 #define OP_NotUsed_127 127 #define OP_NotUsed_128 128 @@ -6886,22 +7084,22 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_IN3 0x0010 /* in3: P3 is an input */ #define OPFLG_OUT3 0x0020 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ -/* 0 */ 0x00, 0x01, 0x00, 0x10, 0x02, 0x11, 0x00, 0x00,\ -/* 8 */ 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 16 */ 0x04, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,\ -/* 24 */ 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00,\ -/* 32 */ 0x02, 0x11, 0x11, 0x02, 0x05, 0x00, 0x02, 0x11,\ -/* 40 */ 0x04, 0x00, 0x00, 0x0c, 0x11, 0x01, 0x02, 0x01,\ -/* 48 */ 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x04, 0x00,\ -/* 56 */ 0x00, 0x00, 0x11, 0x08, 0x2c, 0x2c, 0x00, 0x11,\ -/* 64 */ 0x05, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ -/* 72 */ 0x15, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\ +/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x02, 0x11, 0x00,\ +/* 8 */ 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,\ +/* 16 */ 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,\ +/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00,\ +/* 32 */ 0x00, 0x02, 0x11, 0x11, 0x02, 0x05, 0x00, 0x02,\ +/* 40 */ 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11, 0x01, 0x02,\ +/* 48 */ 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00, 0x04,\ +/* 56 */ 0x00, 0x00, 0x00, 0x11, 0x2c, 0x2c, 0x00, 0x00,\ +/* 64 */ 0x11, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ +/* 72 */ 0x15, 0x05, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\ /* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x04,\ -/* 88 */ 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00,\ -/* 96 */ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x08,\ -/* 104 */ 0x00, 0x02, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x02, 0x00, 0x02, 0x01, 0x11, 0x00, 0x00, 0x05,\ -/* 120 */ 0x00, 0x11, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00,\ +/* 88 */ 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11,\ +/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,\ +/* 104 */ 0x08, 0x00, 0x02, 0x02, 0x05, 0x00, 0x00, 0x00,\ +/* 112 */ 0x00, 0x02, 0x00, 0x02, 0x01, 0x11, 0x00, 0x00,\ +/* 120 */ 0x05, 0x00, 0x11, 0x05, 0x00, 0x02, 0x00, 0x00,\ /* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 136 */ 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,} @@ -6938,7 +7136,7 @@ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); #endif SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); -SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*, int); SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); @@ -6946,6 +7144,14 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n); SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int); +#endif +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int); +SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); + + #ifndef NDEBUG SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); # define VdbeComment(X) sqlite3VdbeComment X @@ -6974,7 +7180,7 @@ SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.69 2008/02/02 20:47:38 drh Exp $ +** @(#) $Id: pager.h,v 1.72 2008/05/01 17:03:49 drh Exp $ */ #ifndef _PAGER_H_ @@ -7012,6 +7218,14 @@ typedef struct PgHdr DbPage; #define PAGER_LOCKINGMODE_EXCLUSIVE 1 /* +** Valid values for the second argument to sqlite3PagerJournalMode(). +*/ +#define PAGER_JOURNALMODE_QUERY -1 +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ + +/* ** See source code comments for a detailed description of the following ** routines: */ @@ -7030,11 +7244,10 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); SQLITE_PRIVATE int sqlite3PagerRef(DbPage*); SQLITE_PRIVATE int sqlite3PagerUnref(DbPage*); SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); -SQLITE_PRIVATE int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*); SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*); SQLITE_PRIVATE int sqlite3PagerTruncate(Pager*,Pgno); SQLITE_PRIVATE int sqlite3PagerBegin(DbPage*, int exFlag); -SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int); SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); SQLITE_PRIVATE int sqlite3PagerIsreadonly(Pager*); @@ -7055,7 +7268,9 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno); SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *, int); SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int); @@ -7176,6 +7391,7 @@ void enable_simulated_io_errors(void); # define INCL_DOSMODULEMGR # define INCL_DOSSEMAPHORES # include +# include # define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) #else # define SQLITE_TEMPNAME_SIZE 200 @@ -7358,11 +7574,7 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); ** register one or more VFS structures using sqlite3_vfs_register() ** before attempting to use SQLite. */ -#if OS_UNIX || OS_WIN || OS_OS2 SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void); -#else -# define sqlite3OsDefaultVfs(X) 0 -#endif #endif /* _SQLITE_OS_H_ */ @@ -7524,6 +7736,11 @@ struct Schema { #define DB_UnresetViews 0x0002 /* Some views have defined column names */ #define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ +/* +** The number of different kinds of things that can be limited +** using the sqlite3_limit() interface. +*/ +#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1) /* ** Each database is an instance of the following structure. @@ -7562,7 +7779,10 @@ struct sqlite3 { u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 dfltLockMode; /* Default locking-mode for attached dbs */ + u8 dfltJournalMode; /* Default journal mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ i64 lastRowid; /* ROWID of most recent insert (see above) */ @@ -7571,6 +7791,7 @@ struct sqlite3 { int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ sqlite3_mutex *mutex; /* Connection mutex */ + int aLimit[SQLITE_N_LIMIT]; /* Limits */ struct sqlite3InitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ @@ -7624,7 +7845,6 @@ struct sqlite3 { #ifdef SQLITE_SSE sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ #endif - u8 dfltLockMode; /* Default locking-mode for attached dbs */ }; /* @@ -8160,15 +8380,17 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags field. */ -#define EP_FromJoin 0x01 /* Originated in ON or USING clause of a join */ -#define EP_Agg 0x02 /* Contains one or more aggregate functions */ -#define EP_Resolved 0x04 /* IDs have been resolved to COLUMNs */ -#define EP_Error 0x08 /* Expression contains one or more errors */ -#define EP_Distinct 0x10 /* Aggregate function with DISTINCT keyword */ -#define EP_VarSelect 0x20 /* pSelect is correlated, not constant */ -#define EP_Dequoted 0x40 /* True if the string has been dequoted */ -#define EP_InfixFunc 0x80 /* True for an infix function: LIKE, GLOB, etc */ -#define EP_ExpCollate 0x100 /* Collating sequence specified explicitly */ +#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ +#define EP_Agg 0x0002 /* Contains one or more aggregate functions */ +#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ +#define EP_Error 0x0008 /* Expression contains one or more errors */ +#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ +#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ +#define EP_Dequoted 0x0040 /* True if the string has been dequoted */ +#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ +#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ +#define EP_FixedDest 0x0400 /* Result needed in a specific register */ /* ** These macros can be used to test, set, or clear bits in the @@ -8325,9 +8547,13 @@ struct WhereLevel { sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */ }; -#define ORDERBY_NORMAL 0 -#define ORDERBY_MIN 1 -#define ORDERBY_MAX 2 +/* +** Flags appropriate for the wflags parameter of sqlite3WhereBegin(). +*/ +#define WHERE_ORDERBY_NORMAL 0 /* No-op */ +#define WHERE_ORDERBY_MIN 1 /* ORDER BY processing for min() func */ +#define WHERE_ORDERBY_MAX 2 /* ORDER BY processing for max() func */ +#define WHERE_ONEPASS_DESIRED 4 /* Want to do one-pass UPDATE/DELETE */ /* ** The WHERE clause processing routine has two halves. The @@ -8337,7 +8563,8 @@ struct WhereLevel { ** into the second half to give some continuity. */ struct WhereInfo { - Parse *pParse; + Parse *pParse; /* Parsing and code generating context */ + u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ SrcList *pTabList; /* List of tables in the join */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ @@ -8453,6 +8680,7 @@ struct SelectDest { u8 affinity; /* Affinity used when eDest==SRT_Set */ int iParm; /* A parameter used by the eDest disposal method */ int iMem; /* Base register where results are written */ + int nMem; /* Number of registers allocated */ }; /* @@ -8491,6 +8719,15 @@ struct Parse { int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int ckBase; /* Base register of data during check constraints */ + int disableColCache; /* True to disable adding to column cache */ + int nColCache; /* Number of entries in the column cache */ + int iColCache; /* Next entry of the cache to replace */ + struct yColCache { + int iTable; /* Table cursor number */ + int iColumn; /* Table column number */ + char affChange; /* True if this register has had an affinity change */ + int iReg; /* Register holding value of this column */ + } aColCache[10]; /* One for each valid column cache entry */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ @@ -8522,7 +8759,8 @@ struct Parse { #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ - Table *pVirtualLock; /* Require virtual table lock on this table */ + int nVtabLock; /* Number of virtual tables to lock */ + Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif #if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 int nHeight; /* Expression tree height of current sub-select */ @@ -8707,6 +8945,7 @@ struct StrAccum { char *zText; /* The string collected so far */ int nChar; /* Length of the string so far */ int nAlloc; /* Amount of space allocated in zText */ + int mxAlloc; /* Maximum allowed string length */ u8 mallocFailed; /* Becomes true if any memory allocation fails */ u8 useMalloc; /* True if zText is enlargable using realloc */ u8 tooBig; /* Becomes true if string size exceeds limits */ @@ -8766,6 +9005,8 @@ SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, int); SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, int); SQLITE_PRIVATE int sqlite3MallocSize(void *); +SQLITE_PRIVATE int sqlite3IsNaN(double); + SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...); SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list); #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) @@ -8819,6 +9060,7 @@ SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32); SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32); SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32); SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*); +SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*); SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); @@ -8855,11 +9097,18 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); -SQLITE_PRIVATE void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int, int); +SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int); +SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int); +SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse*, int); +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int); +SQLITE_PRIVATE int sqlite3ExprWritableRegister(Parse*,int,int); +SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse*,int,int); SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*); +SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int); -SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int); +SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*); +SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); @@ -8876,7 +9125,9 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); SQLITE_PRIVATE Expr *sqlite3CreateIdExpr(Parse *, const char*); -SQLITE_PRIVATE void sqlite3Randomness(int, void*); +SQLITE_PRIVATE void sqlite3PrngSaveState(void); +SQLITE_PRIVATE void sqlite3PrngRestoreState(void); +SQLITE_PRIVATE void sqlite3PrngResetState(void); SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); @@ -8889,7 +9140,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*); SQLITE_PRIVATE int sqlite3IsRowid(const char*); SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*); -SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int); +SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int); SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int); @@ -8914,7 +9165,7 @@ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); -SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, u32, int); +SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, int); #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, @@ -8934,14 +9185,12 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList* SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); SQLITE_PRIVATE void sqlite3DeleteTrigger(Trigger*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); -SQLITE_PRIVATE void sqlite3SelectMask(Parse *, Select *, u32); #else # define sqlite3TriggersExist(A,B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) # define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K) 0 -# define sqlite3SelectMask(A, B, C) #endif SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); @@ -8975,10 +9224,43 @@ SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int); SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE int sqlite3Utf8Read(const u8*, const u8*, const u8**); -SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *, u64); + +/* +** 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. Code should use the MACRO forms below, as the Varint32 versions +** are coded to assume the single byte case is already handled (which +** the MACRO form does). +*/ +SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64); +SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char*, u32); SQLITE_PRIVATE int sqlite3GetVarint(const unsigned char *, u64 *); SQLITE_PRIVATE int sqlite3GetVarint32(const unsigned char *, u32 *); SQLITE_PRIVATE int sqlite3VarintLen(u64 v); + +/* +** The header of a record consists of a sequence variable-length integers. +** These integers are almost always small and are encoded as a single byte. +** The following macros take advantage this fact to provide a fast encode +** and decode of the integers in a record header. It is faster for the common +** case where the integer is a single byte. It is a little slower when the +** integer is two or more bytes. But overall it is faster. +** +** The following expressions are equivalent: +** +** x = sqlite3GetVarint32( A, &B ); +** x = sqlite3PutVarint32( A, B ); +** +** x = getVarint32( A, B ); +** x = putVarint32( A, B ); +** +*/ +#define getVarint32(A,B) ((*(A)<(unsigned char)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), &(B))) +#define putVarint32(A,B) (((B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B))) +#define getVarint sqlite3GetVarint +#define putVarint sqlite3PutVarint + + SQLITE_PRIVATE void sqlite3IndexAffinityStr(Vdbe *, Index *); SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *); SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2); @@ -9055,12 +9337,11 @@ SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(size_t)); SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*)); SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*); +SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3*); #ifndef SQLITE_OMIT_LOAD_EXTENSION SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*); -SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3*); #else # define sqlite3CloseExtensions(X) -# define sqlite3AutoLoadExtensions(X) SQLITE_OK #endif #ifndef SQLITE_OMIT_SHARED_CACHE @@ -9084,6 +9365,7 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, int rc); SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db); SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db); #endif +SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); SQLITE_PRIVATE void sqlite3VtabLock(sqlite3_vtab*); SQLITE_PRIVATE void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*); SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); @@ -9097,7 +9379,7 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *); SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**); SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); -SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*); +SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); @@ -9112,19 +9394,21 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); ** mechanism is disabled at compile-time then set up macros so that no ** unnecessary code is generated. */ -#ifndef SQLITE_OMIT_FAULTINJECTOR +#ifndef SQLITE_OMIT_BUILTIN_TEST SQLITE_PRIVATE void sqlite3FaultConfig(int,int,int); SQLITE_PRIVATE int sqlite3FaultFailures(int); SQLITE_PRIVATE int sqlite3FaultBenignFailures(int); SQLITE_PRIVATE int sqlite3FaultPending(int); -SQLITE_PRIVATE void sqlite3FaultBenign(int,int); +SQLITE_PRIVATE void sqlite3FaultBeginBenign(int); +SQLITE_PRIVATE void sqlite3FaultEndBenign(int); SQLITE_PRIVATE int sqlite3FaultStep(int); #else # define sqlite3FaultConfig(A,B,C) # define sqlite3FaultFailures(A) 0 # define sqlite3FaultBenignFailures(A) 0 # define sqlite3FaultPending(A) (-1) -# define sqlite3FaultBenign(A,B) +# define sqlite3FaultBeginBenign(A) +# define sqlite3FaultEndBenign(A) # define sqlite3FaultStep(A) 0 #endif @@ -9169,11 +9453,11 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *); #ifdef SQLITE_ENABLE_IOTRACE # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); +SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); #else # define IOTRACE(A) # define sqlite3VdbeIOTraceSql(X) #endif -SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); #endif @@ -9197,7 +9481,7 @@ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.76 2008/02/21 20:40:44 drh Exp $ +** $Id: date.c,v 1.79 2008/03/20 14:03:29 drh Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -9502,7 +9786,8 @@ static int parseDateOrTime( return 0; }else if( sqlite3StrICmp(zDate,"now")==0){ double r; - sqlite3OsCurrentTime((sqlite3_vfs *)sqlite3_user_data(context), &r); + sqlite3 *db = sqlite3_context_db_handle(context); + sqlite3OsCurrentTime(db->pVfs, &r); p->rJD = r; p->validJD = 1; return 0; @@ -10017,7 +10302,7 @@ static void strftimeFunc( } if( nSQLITE_MAX_LENGTH ){ + }else if( n>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); return; }else{ @@ -10148,18 +10433,13 @@ static void currentTimeFunc( ){ time_t t; char *zFormat = (char *)sqlite3_user_data(context); + sqlite3 *db; + double rT; char zBuf[20]; - time(&t); -#ifdef SQLITE_TEST - { - extern int sqlite3_current_time; /* See os_XXX.c */ - if( sqlite3_current_time ){ - t = sqlite3_current_time; - } - } -#endif - + db = sqlite3_context_db_handle(context); + sqlite3OsCurrentTime(db->pVfs, &rT); + t = 86400.0*(rT - 2440587.5) + 0.5; #ifdef HAVE_GMTIME_R { struct tm sNow; @@ -10205,7 +10485,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3 *db){ for(i=0; ipVfs), aFuncs[i].xFunc, 0, 0); + SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0); } #else static const struct { @@ -10262,7 +10542,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3 *db){ ** sqlite3OsLock() ** */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) && (OS_WIN==0) #define DO_OS_MALLOC_TEST if (1) { \ void *pTstAlloc = sqlite3_malloc(10); \ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ @@ -10343,7 +10623,14 @@ SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dir return pVfs->xDelete(pVfs, zPath, dirSync); } SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ - return pVfs->xAccess(pVfs, zPath, flags); + int rc; +#ifdef SQLITE_TEST + void *pTstAlloc = sqlite3_malloc(10); + if (!pTstAlloc) return -1; + sqlite3_free(pTstAlloc); +#endif + rc = pVfs->xAccess(pVfs, zPath, flags); + return rc; } SQLITE_PRIVATE int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){ return pVfs->xGetTempname(pVfs, nBufOut, zBufOut); @@ -10400,10 +10687,9 @@ SQLITE_PRIVATE int sqlite3OsOpenMalloc( } SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){ int rc = SQLITE_OK; - if( pFile ){ - rc = sqlite3OsClose(pFile); - sqlite3_free(pFile); - } + assert( pFile ); + rc = sqlite3OsClose(pFile); + sqlite3_free(pFile); return rc; } @@ -10494,6 +10780,14 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ return SQLITE_OK; } +/* +** Provide a default sqlite3OsDefaultVfs() implementation in the +** cases where none of the standard backends are used. +*/ +#if !OS_UNIX && !OS_WIN && !OS_OS2 +SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void){ return 0; } +#endif + /************** End of os.c **************************************************/ /************** Begin file fault.c *******************************************/ /* @@ -10517,7 +10811,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ ** allocation failures or I/O errors. ** ** The fault injector is omitted from the code if SQLite is -** compiled with -DSQLITE_OMIT_FAULTINJECTOR=1. There is a very +** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1. There is a very ** small performance hit for leaving the fault injector in the code. ** Commerical products will probably want to omit the fault injector ** from production builds. But safety-critical systems who work @@ -10525,7 +10819,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ ** choose to leave the fault injector enabled even in production. */ -#ifndef SQLITE_OMIT_FAULTINJECTOR +#ifndef SQLITE_OMIT_BUILTIN_TEST /* ** There can be various kinds of faults. For example, there can be @@ -10539,7 +10833,7 @@ static struct FaultInjector { int nBenign; /* Number of benign failures seen since last config */ int nFail; /* Number of failures seen since last config */ u8 enable; /* True if enabled */ - u8 benign; /* Ture if next failure will be benign */ + i16 benign; /* Positive if next failure will be benign */ } aFault[SQLITE_FAULTINJECTOR_COUNT]; /* @@ -10601,9 +10895,27 @@ SQLITE_PRIVATE int sqlite3FaultPending(int id){ ** will continue to function normally. So a malloc failure during ** a hash table resize is a benign fault. */ -SQLITE_PRIVATE void sqlite3FaultBenign(int id, int enable){ - assert( id>=0 && id=0 && id0 ); + aFault[id].benign--; + } + }else{ + assert( id>=0 && id0 ); + aFault[id].benign--; + } } /* @@ -10631,7 +10943,7 @@ SQLITE_PRIVATE int sqlite3FaultStep(int id){ } sqlite3Fault(); aFault[id].nFail++; - if( aFault[id].benign ){ + if( aFault[id].benign>0 ){ aFault[id].nBenign++; } aFault[id].nRepeat--; @@ -10641,7 +10953,7 @@ SQLITE_PRIVATE int sqlite3FaultStep(int id){ return 1; } -#endif /* SQLITE_OMIT_FAULTINJECTOR */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ /************** End of fault.c ***********************************************/ /************** Begin file mem1.c ********************************************/ @@ -10659,7 +10971,7 @@ SQLITE_PRIVATE int sqlite3FaultStep(int id){ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem1.c,v 1.16 2008/02/14 23:26:56 drh Exp $ +** $Id: mem1.c,v 1.17 2008/03/18 00:07:11 drh Exp $ */ /* @@ -10783,10 +11095,14 @@ SQLITE_API void *sqlite3_malloc(int nBytes){ if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ sqlite3MemsysAlarm(nBytes); } - p = malloc(nBytes+8); - if( p==0 ){ - sqlite3MemsysAlarm(nBytes); + if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){ + p = 0; + }else{ p = malloc(nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = malloc(nBytes+8); + } } if( p ){ p[0] = nBytes; @@ -10851,12 +11167,16 @@ SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){ if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){ sqlite3MemsysAlarm(nBytes-nOld); } - p = realloc(p, nBytes+8); - if( p==0 ){ - sqlite3MemsysAlarm(nBytes); - p = pPrior; - p--; + if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){ + p = 0; + }else{ p = realloc(p, nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = pPrior; + p--; + p = realloc(p, nBytes+8); + } } if( p ){ p[0] = nBytes; @@ -10888,7 +11208,7 @@ SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem2.c,v 1.22 2008/02/19 15:15:16 drh Exp $ +** $Id: mem2.c,v 1.26 2008/04/10 14:57:25 drh Exp $ */ /* @@ -10922,8 +11242,8 @@ SQLITE_API void *sqlite3_realloc(void *pPrior, int nBytes){ ** MemBlockHdr. */ struct MemBlockHdr { + i64 iSize; /* Size of this allocation */ struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ - int iSize; /* Size of this allocation */ char nBacktrace; /* Number of backtraces on this alloc */ char nBacktraceSlots; /* Available backtrace slots */ short nTitle; /* Bytes of title; includes '\0' */ @@ -10981,6 +11301,7 @@ static struct { ** The number of levels of backtrace to save in new allocations. */ int nBacktrace; + void (*xBacktrace)(int, int, void **); /* ** Title text to insert in front of each block @@ -11085,13 +11406,19 @@ static void sqlite3MemsysAlarm(int nByte){ static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ struct MemBlockHdr *p; int *pInt; + u8 *pU8; + int nReserve; p = (struct MemBlockHdr*)pAllocation; p--; assert( p->iForeGuard==FOREGUARD ); - assert( (p->iSize & 3)==0 ); + nReserve = (p->iSize+7)&~7; pInt = (int*)pAllocation; - assert( pInt[p->iSize/sizeof(int)]==REARGUARD ); + pU8 = (u8*)pAllocation; + assert( pInt[nReserve/sizeof(int)]==REARGUARD ); + assert( (nReserve-0)<=p->iSize || pU8[nReserve-1]==0x65 ); + assert( (nReserve-1)<=p->iSize || pU8[nReserve-2]==0x65 ); + assert( (nReserve-2)<=p->iSize || pU8[nReserve-3]==0x65 ); return p; } @@ -11119,18 +11446,19 @@ SQLITE_API void *sqlite3_malloc(int nByte){ int totalSize; if( nByte>0 ){ + int nReserve; enterMem(); assert( mem.disallow==0 ); if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){ sqlite3MemsysAlarm(nByte); } - nByte = (nByte+3)&~3; - if( nByte/8>NCSIZE-1 ){ + nReserve = (nByte+7)&~7; + if( nReserve/8>NCSIZE-1 ){ mem.sizeCnt[NCSIZE-1]++; }else{ - mem.sizeCnt[nByte/8]++; + mem.sizeCnt[nReserve/8]++; } - totalSize = nByte + sizeof(*pHdr) + sizeof(int) + + totalSize = nReserve + sizeof(*pHdr) + sizeof(int) + mem.nBacktrace*sizeof(void*) + mem.nTitle; if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){ p = 0; @@ -11160,6 +11488,9 @@ SQLITE_API void *sqlite3_malloc(int nByte){ void *aAddr[40]; pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); + if( mem.xBacktrace ){ + mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]); + } }else{ pHdr->nBacktrace = 0; } @@ -11168,8 +11499,8 @@ SQLITE_API void *sqlite3_malloc(int nByte){ } pHdr->iSize = nByte; pInt = (int*)&pHdr[1]; - pInt[nByte/sizeof(int)] = REARGUARD; - memset(pInt, 0x65, nByte); + pInt[nReserve/sizeof(int)] = REARGUARD; + memset(pInt, 0x65, nReserve); mem.nowUsed += nByte; if( mem.nowUsed>mem.mxUsed ){ mem.mxUsed = mem.nowUsed; @@ -11263,6 +11594,10 @@ SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){ mem.nBacktrace = depth; } +SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){ + mem.xBacktrace = xBacktrace; +} + /* ** Set the title string for subsequent allocations. */ @@ -11272,10 +11607,19 @@ SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){ if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; memcpy(mem.zTitle, zTitle, n); mem.zTitle[n] = 0; - mem.nTitle = (n+3)&~3; + mem.nTitle = (n+7)&~7; sqlite3_mutex_leave(mem.mutex); } +SQLITE_PRIVATE void sqlite3MemdebugSync(){ + struct MemBlockHdr *pHdr; + for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ + void **pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]); + } +} + /* ** Open the file indicated and write a log of all unfreed memory ** allocations into that log. @@ -11294,7 +11638,7 @@ SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){ for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ char *z = (char*)pHdr; z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; - fprintf(out, "**** %d bytes at %p from %s ****\n", + fprintf(out, "**** %lld bytes at %p from %s ****\n", pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); if( pHdr->nBacktrace ){ fflush(out); @@ -12522,7 +12866,7 @@ SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){ ** implementation is suitable for testing. ** debugging purposes ** -** $Id: mutex.c,v 1.16 2007/09/10 16:13:00 danielk1977 Exp $ +** $Id: mutex.c,v 1.17 2008/03/26 18:34:43 danielk1977 Exp $ */ #ifdef SQLITE_MUTEX_NOOP_DEBUG @@ -12546,7 +12890,7 @@ struct sqlite3_mutex { ** that means that a mutex could not be allocated. */ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){ - static sqlite3_mutex aStatic[5]; + static sqlite3_mutex aStatic[6]; sqlite3_mutex *pNew = 0; switch( id ){ case SQLITE_MUTEX_FAST: @@ -12642,7 +12986,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ************************************************************************* ** This file contains the C functions that implement mutexes for OS/2 ** -** $Id: mutex_os2.c,v 1.5 2008/02/01 19:42:38 pweilbacher Exp $ +** $Id: mutex_os2.c,v 1.6 2008/03/26 18:34:43 danielk1977 Exp $ */ /* @@ -12731,6 +13075,7 @@ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int iType){ { OS2_MUTEX_INITIALIZER, }, { OS2_MUTEX_INITIALIZER, }, { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, }; if ( !isInit ){ APIRET rc; @@ -12889,7 +13234,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** -** $Id: mutex_unix.c,v 1.5 2007/11/28 14:04:57 drh Exp $ +** $Id: mutex_unix.c,v 1.7 2008/03/29 12:47:27 rse Exp $ */ /* @@ -12916,6 +13261,11 @@ struct sqlite3_mutex { int trace; /* True to trace changes */ #endif }; +#ifdef SQLITE_DEBUG +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 } +#else +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0 } +#endif /* ** The sqlite3_mutex_alloc() routine allocates a new @@ -12960,11 +13310,12 @@ struct sqlite3_mutex { */ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int iType){ static sqlite3_mutex staticMutexes[] = { - { PTHREAD_MUTEX_INITIALIZER, }, - { PTHREAD_MUTEX_INITIALIZER, }, - { PTHREAD_MUTEX_INITIALIZER, }, - { PTHREAD_MUTEX_INITIALIZER, }, - { PTHREAD_MUTEX_INITIALIZER, }, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER, + SQLITE3_MUTEX_INITIALIZER }; sqlite3_mutex *p; switch( iType ){ @@ -13189,7 +13540,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ************************************************************************* ** This file contains the C functions that implement mutexes for win32 ** -** $Id: mutex_w32.c,v 1.5 2007/10/05 15:08:01 drh Exp $ +** $Id: mutex_w32.c,v 1.6 2008/03/26 18:34:43 danielk1977 Exp $ */ /* @@ -13288,7 +13639,7 @@ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int iType){ break; } default: { - static sqlite3_mutex staticMutexes[5]; + static sqlite3_mutex staticMutexes[6]; static int isInit = 0; while( !isInit ){ static long lock = 0; @@ -13411,7 +13762,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){ ** Memory allocation functions used throughout sqlite. ** ** -** $Id: malloc.c,v 1.14 2007/10/20 16:36:31 drh Exp $ +** $Id: malloc.c,v 1.15 2008/03/26 18:34:43 danielk1977 Exp $ */ /* @@ -13455,7 +13806,9 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){ */ SQLITE_API int sqlite3_release_memory(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT - return sqlite3PagerReleaseMemory(n); + int nRet = sqlite3VdbeReleaseMemory(n); + nRet += sqlite3PagerReleaseMemory(n-nRet); + return nRet; #else return SQLITE_OK; #endif @@ -14111,7 +14464,7 @@ static void vxprintf( if( xtype==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; - if( sqlite3_isnan(realvalue) ){ + if( sqlite3IsNaN(realvalue) ){ bufpt = "NaN"; length = 3; break; @@ -14264,8 +14617,11 @@ static void vxprintf( }else if( xtype==etDYNSTRING ){ zExtra = bufpt; } - length = strlen(bufpt); - if( precision>=0 && precision=0 ){ + for(length=0; lengthnAlloc += p->nAlloc + N + 1; - if( p->nAlloc > SQLITE_MAX_LENGTH ){ - p->nAlloc = SQLITE_MAX_LENGTH; - if( p->nChar+N >= p->nAlloc ){ + i64 szNew = p->nAlloc; + szNew += N + 1; + if( szNew > p->mxAlloc ){ + p->nAlloc = p->mxAlloc; + if( ((i64)p->nChar)+((i64)N) >= p->nAlloc ){ sqlite3StrAccumReset(p); p->tooBig = 1; return; } + }else{ + p->nAlloc = szNew; } zNew = sqlite3_malloc( p->nAlloc ); if( zNew ){ @@ -14430,10 +14789,11 @@ SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){ /* ** Initialize a string accumulator */ -static void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n){ +static void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ p->zText = p->zBase = zBase; p->nChar = 0; p->nAlloc = n; + p->mxAlloc = mx; p->useMalloc = 1; p->tooBig = 0; p->mallocFailed = 0; @@ -14447,7 +14807,8 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; - sqlite3StrAccumInit(&acc, zBase, sizeof(zBase)); + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), + db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH); vxprintf(&acc, 1, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.mallocFailed && db ){ @@ -14477,7 +14838,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){ char *z; char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; - sqlite3StrAccumInit(&acc, zBase, sizeof(zBase)); + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); vxprintf(&acc, 0, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; @@ -14510,7 +14871,7 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ if( n<=0 ){ return zBuf; } - sqlite3StrAccumInit(&acc, zBuf, n); + sqlite3StrAccumInit(&acc, zBuf, n, 0); acc.useMalloc = 0; va_start(ap,zFormat); vxprintf(&acc, 0, zFormat, ap); @@ -14529,7 +14890,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ va_list ap; StrAccum acc; char zBuf[500]; - sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf)); + sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); acc.useMalloc = 0; va_start(ap,zFormat); vxprintf(&acc, 0, zFormat, ap); @@ -14559,7 +14920,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.21 2008/01/16 17:46:38 drh Exp $ +** $Id: random.c,v 1.23 2008/03/21 16:45:47 drh Exp $ */ @@ -14633,7 +14994,7 @@ static int randomByte(void){ /* ** Return N random bytes. */ -SQLITE_PRIVATE void sqlite3Randomness(int N, void *pBuf){ +SQLITE_API void sqlite3_randomness(int N, void *pBuf){ unsigned char *zBuf = pBuf; static sqlite3_mutex *mutex = 0; if( mutex==0 ){ @@ -14646,22 +15007,24 @@ SQLITE_PRIVATE void sqlite3Randomness(int N, void *pBuf){ sqlite3_mutex_leave(mutex); } -#ifdef SQLITE_TEST +#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. +** The sqlite3_test_control() interface calls these routines to +** control the PRNG. */ static struct sqlite3PrngType sqlite3SavedPrng; -SQLITE_PRIVATE void sqlite3SavePrngState(void){ +SQLITE_PRIVATE void sqlite3PrngSaveState(void){ memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng)); } -SQLITE_PRIVATE void sqlite3RestorePrngState(void){ +SQLITE_PRIVATE void sqlite3PrngRestoreState(void){ memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng)); } -SQLITE_PRIVATE void sqlite3ResetPrngState(void){ +SQLITE_PRIVATE void sqlite3PrngResetState(void){ sqlite3Prng.isInit = 0; } -#endif /* SQLITE_TEST */ +#endif /* SQLITE_OMIT_BUILTIN_TEST */ /************** End of random.c **********************************************/ /************** Begin file utf.c *********************************************/ @@ -14679,7 +15042,7 @@ SQLITE_PRIVATE void sqlite3ResetPrngState(void){ ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.60 2008/02/13 18:25:27 danielk1977 Exp $ +** $Id: utf.c,v 1.61 2008/03/28 15:44:10 danielk1977 Exp $ ** ** Notes on UTF-8: ** @@ -14771,6 +15134,7 @@ struct Cursor { Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ + Bool ephemPseudoTable; Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ @@ -14829,6 +15193,7 @@ struct Mem { u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ void (*xDel)(void *); /* If not null, call this function to delete Mem.z */ + char *zMalloc; /* Dynamic buffer allocated by sqlite3_malloc() */ }; /* One or more of the following flags are set to indicate the validOK @@ -15039,6 +15404,32 @@ struct Vdbe { int fetchId; /* Statement number used by sqlite3_fetch_statement */ int lru; /* Counter used for LRU cache replacement */ #endif +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Vdbe *pLruPrev; + Vdbe *pLruNext; +#endif +}; + +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassemblied by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constitutent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u8 needFree; /* True if memory obtained from sqlite3_malloc() */ + u8 needDestroy; /* True if apMem[]s should be destroyed on close */ + Mem *aMem; /* Values */ }; /* @@ -15065,10 +15456,9 @@ SQLITE_PRIVATE int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); -SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,int,const unsigned char*,int*); +SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*); SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *); SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); -SQLITE_PRIVATE int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*); SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); @@ -15095,10 +15485,14 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); +SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); SQLITE_PRIVATE const char *sqlite3OpcodeName(int); SQLITE_PRIVATE int sqlite3VdbeOpcodeHasProperty(int, int); SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +SQLITE_PRIVATE int sqlite3VdbeReleaseBuffers(Vdbe *p); +#endif #ifndef NDEBUG SQLITE_PRIVATE void sqlite3VdbeMemSanity(Mem*); @@ -15392,6 +15786,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ pMem->enc = desiredEnc; pMem->flags |= (MEM_Term|MEM_Dyn); pMem->z = (char*)zOut; + pMem->zMalloc = pMem->z; translate_out: #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) @@ -15626,11 +16021,28 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(){ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.216 2008/01/23 03:03:05 drh Exp $ +** $Id: util.c,v 1.229 2008/05/13 16:41:50 drh Exp $ */ /* +** Return true if the floating point value is Not a Number. +*/ +SQLITE_PRIVATE int sqlite3IsNaN(double x){ + /* This NaN test sometimes fails if compiled on GCC with -ffast-math. + ** On the other hand, the use of -ffast-math comes with the following + ** warning: + ** + ** This option [-ffast-math] should never be turned on by any + ** -O option since it can result in incorrect output for programs + ** which depend on an exact implementation of IEEE or ISO + ** rules/specifications for math functions. + */ + volatile double y = x; + return x!=y; +} + +/* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". ** @@ -15854,6 +16266,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){ int sign = 1; const char *zBegin = z; LONGDOUBLE_TYPE v1 = 0.0; + int nSignificant = 0; while( isspace(*(u8*)z) ) z++; if( *z=='-' ){ sign = -1; @@ -15861,16 +16274,29 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult){ }else if( *z=='+' ){ z++; } + while( z[0]=='0' ){ + z++; + } while( isdigit(*(u8*)z) ){ v1 = v1*10.0 + (*z - '0'); z++; + nSignificant++; } if( *z=='.' ){ LONGDOUBLE_TYPE divisor = 1.0; z++; + if( nSignificant==0 ){ + while( z[0]=='0' ){ + divisor *= 10.0; + z++; + } + } while( isdigit(*(u8*)z) ){ - v1 = v1*10.0 + (*z - '0'); - divisor *= 10.0; + if( nSignificant<18 ){ + v1 = v1*10.0 + (*z - '0'); + divisor *= 10.0; + nSignificant++; + } z++; } v1 /= divisor; @@ -16107,71 +16533,271 @@ SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){ } /* +** This routine is a faster version of sqlite3PutVarint() that only +** works for 32-bit positive integers and which is optimized for +** the common case of small integers. A MACRO version, putVarint32, +** is provided which inlines the single-byte case. All code should use +** the MACRO version as this function assumes the single-byte case has +** already been handled. +*/ +SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char *p, u32 v){ +#ifndef putVarint32 + if( (v & ~0x7f)==0 ){ + p[0] = v; + return 1; + } +#endif + if( (v & ~0x3fff)==0 ){ + p[0] = (v>>7) | 0x80; + p[1] = v & 0x7f; + return 2; + } + return sqlite3PutVarint(p, v); +} + +/* ** Read a 64-bit variable-length integer from memory starting at p[0]. ** Return the number of bytes read. The value is stored in *v. */ SQLITE_PRIVATE int sqlite3GetVarint(const unsigned char *p, u64 *v){ - u32 x; - u64 x64; - int n; - unsigned char c; - if( ((c = p[0]) & 0x80)==0 ){ - *v = c; + u32 a,b,s; + + a = *p; + // a: p0 (unmasked) + if (!(a&0x80)) + { + *v = a; return 1; } - x = c & 0x7f; - if( ((c = p[1]) & 0x80)==0 ){ - *v = (x<<7) | c; + + p++; + b = *p; + // b: p1 (unmasked) + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + a |= b; + *v = a; return 2; } - x = (x<<7) | (c&0x7f); - if( ((c = p[2]) & 0x80)==0 ){ - *v = (x<<7) | c; + + p++; + a = a<<14; + a |= *p; + // a: p0<<14 | p2 (unmasked) + if (!(a&0x80)) + { + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + a |= b; + *v = a; return 3; } - x = (x<<7) | (c&0x7f); - if( ((c = p[3]) & 0x80)==0 ){ - *v = (x<<7) | c; + + // CSE1 from below + a &= (0x7f<<14)|(0x7f); + p++; + b = b<<14; + b |= *p; + // b: p1<<14 | p3 (unmasked) + if (!(b&0x80)) + { + b &= (0x7f<<14)|(0x7f); + // moved CSE1 up + // a &= (0x7f<<14)|(0x7f); + a = a<<7; + a |= b; + *v = a; return 4; } - x64 = (x<<7) | (c&0x7f); - n = 4; - do{ - c = p[n++]; - if( n==9 ){ - x64 = (x64<<8) | c; - break; - } - x64 = (x64<<7) | (c&0x7f); - }while( (c & 0x80)!=0 ); - *v = x64; - return n; + + // a: p0<<14 | p2 (masked) + // b: p1<<14 | p3 (unmasked) + // 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) + // moved CSE1 up + // a &= (0x7f<<14)|(0x7f); + b &= (0x7f<<14)|(0x7f); + s = a; + // s: p0<<14 | p2 (masked) + + p++; + a = a<<14; + a |= *p; + // a: p0<<28 | p2<<14 | p4 (unmasked) + if (!(a&0x80)) + { + // we can skip these cause they were (effectively) done above in calc'ing s + // a &= (0x7f<<28)|(0x7f<<14)|(0x7f); + // b &= (0x7f<<14)|(0x7f); + b = b<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 5; + } + + // 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) + s = s<<7; + s |= b; + // s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) + + p++; + b = b<<14; + b |= *p; + // b: p1<<28 | p3<<14 | p5 (unmasked) + if (!(b&0x80)) + { + // we can skip this cause it was (effectively) done above in calc'ing s + // b &= (0x7f<<28)|(0x7f<<14)|(0x7f); + a &= (0x7f<<14)|(0x7f); + a = a<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 6; + } + + p++; + a = a<<14; + a |= *p; + // a: p2<<28 | p4<<14 | p6 (unmasked) + if (!(a&0x80)) + { + a &= (0x7f<<28)|(0x7f<<14)|(0x7f); + b &= (0x7f<<14)|(0x7f); + b = b<<7; + a |= b; + s = s>>11; + *v = ((u64)s)<<32 | a; + return 7; + } + + // CSE2 from below + a &= (0x7f<<14)|(0x7f); + p++; + b = b<<14; + b |= *p; + // b: p3<<28 | p5<<14 | p7 (unmasked) + if (!(b&0x80)) + { + b &= (0x7f<<28)|(0x7f<<14)|(0x7f); + // moved CSE2 up + // a &= (0x7f<<14)|(0x7f); + a = a<<7; + a |= b; + s = s>>4; + *v = ((u64)s)<<32 | a; + return 8; + } + + p++; + a = a<<15; + a |= *p; + // a: p4<<29 | p6<<15 | p8 (unmasked) + + // moved CSE2 up + // a &= (0x7f<<29)|(0x7f<<15)|(0xff); + b &= (0x7f<<14)|(0x7f); + b = b<<8; + a |= b; + + s = s<<4; + b = p[-4]; + b &= 0x7f; + b = b>>3; + s |= b; + + *v = ((u64)s)<<32 | a; + + return 9; } /* ** Read a 32-bit variable-length integer from memory starting at p[0]. ** Return the number of bytes read. The value is stored in *v. +** A MACRO version, getVarint32, is provided which inlines the +** single-byte case. All code should use the MACRO version as +** this function assumes the single-byte case has already been handled. */ SQLITE_PRIVATE int sqlite3GetVarint32(const unsigned char *p, u32 *v){ - u32 x; - int n; - unsigned char c; - if( ((signed char*)p)[0]>=0 ){ - *v = p[0]; + u32 a,b; + + a = *p; + // a: p0 (unmasked) +#ifndef getVarint32 + if (!(a&0x80)) + { + *v = a; return 1; } - x = p[0] & 0x7f; - if( ((signed char*)p)[1]>=0 ){ - *v = (x<<7) | p[1]; +#endif + + p++; + b = *p; + // b: p1 (unmasked) + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + *v = a | b; return 2; } - x = (x<<7) | (p[1] & 0x7f); - n = 2; - do{ - x = (x<<7) | ((c = p[n++])&0x7f); - }while( (c & 0x80)!=0 && n<9 ); - *v = x; - return n; + + p++; + a = a<<14; + a |= *p; + // a: p0<<14 | p2 (unmasked) + if (!(a&0x80)) + { + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + *v = a | b; + return 3; + } + + p++; + b = b<<14; + b |= *p; + // b: p1<<14 | p3 (unmasked) + if (!(b&0x80)) + { + b &= (0x7f<<14)|(0x7f); + a &= (0x7f<<14)|(0x7f); + a = a<<7; + *v = a | b; + return 4; + } + + p++; + a = a<<14; + a |= *p; + // a: p0<<28 | p2<<14 | p4 (unmasked) + if (!(a&0x80)) + { + a &= (0x7f<<28)|(0x7f<<14)|(0x7f); + b &= (0x7f<<28)|(0x7f<<14)|(0x7f); + b = b<<7; + *v = a | b; + return 5; + } + + /* We can only reach this point when reading a corrupt database + ** file. In that case we are not in any hurry. Use the (relatively + ** slow) general-purpose sqlite3GetVarint() routine to extract the + ** value. */ + { + u64 v64; + int n; + + p -= 4; + n = sqlite3GetVarint(p, &v64); + assert( n>5 && n<=9 ); + *v = (u32)v64; + return n; + } } /* @@ -16203,22 +16829,23 @@ SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){ -#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) \ - || defined(SQLITE_TEST) +#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* ** Translate a single byte of Hex into an integer. +** This routinen only works if h really is a valid hexadecimal +** character: 0..9a..fA..F */ static int hexToInt(int h){ - if( h>='0' && h<='9' ){ - return h - '0'; - }else if( h>='a' && h<='f' ){ - return h - 'a' + 10; - }else{ - assert( h>='A' && h<='F' ); - return h - 'A' + 10; - } + assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); +#ifdef SQLITE_ASCII + h += 9*(1&(h>>6)); +#endif +#ifdef SQLITE_EBCDIC + h += 9*(1&~(h>>4)); +#endif + return h & 0xf; } -#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC || SQLITE_TEST */ +#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* @@ -16273,6 +16900,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3 *db){ if( db->magic==SQLITE_MAGIC_OPEN ){ db->magic = SQLITE_MAGIC_BUSY; + assert( sqlite3_mutex_held(db->mutex) ); return 0; }else if( db->magic==SQLITE_MAGIC_BUSY ){ db->magic = SQLITE_MAGIC_ERROR; @@ -16291,6 +16919,7 @@ SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3 *db){ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){ if( db->magic==SQLITE_MAGIC_BUSY ){ db->magic = SQLITE_MAGIC_OPEN; + assert( sqlite3_mutex_held(db->mutex) ); return 0; }else{ db->magic = SQLITE_MAGIC_ERROR; @@ -16348,7 +16977,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: hash.c,v 1.26 2008/02/18 22:24:58 drh Exp $ +** $Id: hash.c,v 1.28 2008/05/13 13:27:34 drh Exp $ */ /* Turn bulk memory into a hash table object by initializing the @@ -16387,7 +17016,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){ assert( pH!=0 ); elem = pH->first; pH->first = 0; - if( pH->ht ) sqlite3_free(pH->ht); + sqlite3_free(pH->ht); pH->ht = 0; pH->htsize = 0; while( elem ){ @@ -16567,12 +17196,12 @@ static void rehash(Hash *pH, int new_size){ ** is benign (since failing to resize a hash table is a performance ** hit only, not a fatal error). */ - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pH->htsize>0); + if( pH->htsize>0 ) sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC); new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) ); - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + if( pH->htsize>0 ) sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC); if( new_ht==0 ) return; - if( pH->ht ) sqlite3_free(pH->ht); + sqlite3_free(pH->ht); pH->ht = new_ht; pH->htsize = new_size; xHash = hashFunction(pH->keyClass); @@ -16764,69 +17393,69 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, voi SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ static const char *const azName[] = { "?", /* 1 */ "VNext", - /* 2 */ "Column", - /* 3 */ "SetCookie", - /* 4 */ "Sequence", - /* 5 */ "MoveGt", - /* 6 */ "RowKey", - /* 7 */ "SCopy", - /* 8 */ "OpenWrite", - /* 9 */ "If", - /* 10 */ "VRowid", - /* 11 */ "CollSeq", - /* 12 */ "OpenRead", - /* 13 */ "Expire", - /* 14 */ "AutoCommit", - /* 15 */ "IntegrityCk", + /* 2 */ "Affinity", + /* 3 */ "Column", + /* 4 */ "SetCookie", + /* 5 */ "Sequence", + /* 6 */ "MoveGt", + /* 7 */ "RowKey", + /* 8 */ "SCopy", + /* 9 */ "OpenWrite", + /* 10 */ "If", + /* 11 */ "VRowid", + /* 12 */ "CollSeq", + /* 13 */ "OpenRead", + /* 14 */ "Expire", + /* 15 */ "AutoCommit", /* 16 */ "Not", - /* 17 */ "Sort", - /* 18 */ "Copy", - /* 19 */ "Trace", - /* 20 */ "Function", - /* 21 */ "IfNeg", - /* 22 */ "Noop", - /* 23 */ "Return", - /* 24 */ "NewRowid", - /* 25 */ "Variable", - /* 26 */ "String", - /* 27 */ "RealAffinity", - /* 28 */ "VRename", - /* 29 */ "ParseSchema", - /* 30 */ "VOpen", - /* 31 */ "Close", - /* 32 */ "CreateIndex", - /* 33 */ "IsUnique", - /* 34 */ "NotFound", - /* 35 */ "Int64", - /* 36 */ "MustBeInt", - /* 37 */ "Halt", - /* 38 */ "Rowid", - /* 39 */ "IdxLT", - /* 40 */ "AddImm", - /* 41 */ "Statement", - /* 42 */ "RowData", - /* 43 */ "MemMax", - /* 44 */ "NotExists", - /* 45 */ "Gosub", - /* 46 */ "Integer", - /* 47 */ "Prev", - /* 48 */ "VColumn", - /* 49 */ "CreateTable", - /* 50 */ "Last", - /* 51 */ "IncrVacuum", - /* 52 */ "IdxRowid", - /* 53 */ "ResetCount", - /* 54 */ "FifoWrite", - /* 55 */ "ContextPush", - /* 56 */ "DropTrigger", - /* 57 */ "DropIndex", - /* 58 */ "IdxGE", - /* 59 */ "IdxDelete", + /* 17 */ "IntegrityCk", + /* 18 */ "Sort", + /* 19 */ "Copy", + /* 20 */ "Trace", + /* 21 */ "Function", + /* 22 */ "IfNeg", + /* 23 */ "Noop", + /* 24 */ "Return", + /* 25 */ "NewRowid", + /* 26 */ "Variable", + /* 27 */ "String", + /* 28 */ "RealAffinity", + /* 29 */ "VRename", + /* 30 */ "ParseSchema", + /* 31 */ "VOpen", + /* 32 */ "Close", + /* 33 */ "CreateIndex", + /* 34 */ "IsUnique", + /* 35 */ "NotFound", + /* 36 */ "Int64", + /* 37 */ "MustBeInt", + /* 38 */ "Halt", + /* 39 */ "Rowid", + /* 40 */ "IdxLT", + /* 41 */ "AddImm", + /* 42 */ "Statement", + /* 43 */ "RowData", + /* 44 */ "MemMax", + /* 45 */ "NotExists", + /* 46 */ "Gosub", + /* 47 */ "Integer", + /* 48 */ "Prev", + /* 49 */ "VColumn", + /* 50 */ "CreateTable", + /* 51 */ "Last", + /* 52 */ "IncrVacuum", + /* 53 */ "IdxRowid", + /* 54 */ "ResetCount", + /* 55 */ "FifoWrite", + /* 56 */ "ContextPush", + /* 57 */ "DropTrigger", + /* 58 */ "DropIndex", + /* 59 */ "IdxGE", /* 60 */ "Or", /* 61 */ "And", - /* 62 */ "Vacuum", - /* 63 */ "MoveLe", - /* 64 */ "IfNot", + /* 62 */ "IdxDelete", + /* 63 */ "Vacuum", + /* 64 */ "MoveLe", /* 65 */ "IsNull", /* 66 */ "NotNull", /* 67 */ "Ne", @@ -16835,7 +17464,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 70 */ "Le", /* 71 */ "Lt", /* 72 */ "Ge", - /* 73 */ "DropTable", + /* 73 */ "IfNot", /* 74 */ "BitAnd", /* 75 */ "BitOr", /* 76 */ "ShiftLeft", @@ -16846,47 +17475,47 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 81 */ "Divide", /* 82 */ "Remainder", /* 83 */ "Concat", - /* 84 */ "MakeRecord", - /* 85 */ "ResultRow", - /* 86 */ "Delete", + /* 84 */ "DropTable", + /* 85 */ "MakeRecord", + /* 86 */ "ResultRow", /* 87 */ "BitNot", /* 88 */ "String8", - /* 89 */ "AggFinal", - /* 90 */ "Goto", - /* 91 */ "TableLock", - /* 92 */ "FifoRead", - /* 93 */ "Clear", - /* 94 */ "MoveLt", - /* 95 */ "VerifyCookie", - /* 96 */ "AggStep", - /* 97 */ "SetNumColumns", - /* 98 */ "Transaction", - /* 99 */ "VFilter", - /* 100 */ "VDestroy", - /* 101 */ "ContextPop", - /* 102 */ "Next", - /* 103 */ "IdxInsert", - /* 104 */ "Insert", - /* 105 */ "Destroy", - /* 106 */ "ReadCookie", - /* 107 */ "ForceInt", - /* 108 */ "LoadAnalysis", - /* 109 */ "Explain", - /* 110 */ "OpenPseudo", - /* 111 */ "OpenEphemeral", - /* 112 */ "Null", - /* 113 */ "Move", - /* 114 */ "Blob", - /* 115 */ "Rewind", - /* 116 */ "MoveGe", - /* 117 */ "VBegin", - /* 118 */ "VUpdate", - /* 119 */ "IfZero", - /* 120 */ "VCreate", - /* 121 */ "Found", - /* 122 */ "IfPos", - /* 123 */ "NullRow", - /* 124 */ "NotUsed_124", + /* 89 */ "Delete", + /* 90 */ "AggFinal", + /* 91 */ "Goto", + /* 92 */ "TableLock", + /* 93 */ "FifoRead", + /* 94 */ "Clear", + /* 95 */ "MoveLt", + /* 96 */ "VerifyCookie", + /* 97 */ "AggStep", + /* 98 */ "SetNumColumns", + /* 99 */ "Transaction", + /* 100 */ "VFilter", + /* 101 */ "VDestroy", + /* 102 */ "ContextPop", + /* 103 */ "Next", + /* 104 */ "IdxInsert", + /* 105 */ "Insert", + /* 106 */ "Destroy", + /* 107 */ "ReadCookie", + /* 108 */ "ForceInt", + /* 109 */ "LoadAnalysis", + /* 110 */ "Explain", + /* 111 */ "OpenPseudo", + /* 112 */ "OpenEphemeral", + /* 113 */ "Null", + /* 114 */ "Move", + /* 115 */ "Blob", + /* 116 */ "Rewind", + /* 117 */ "MoveGe", + /* 118 */ "VBegin", + /* 119 */ "VUpdate", + /* 120 */ "IfZero", + /* 121 */ "VCreate", + /* 122 */ "Found", + /* 123 */ "IfPos", + /* 124 */ "NullRow", /* 125 */ "Real", /* 126 */ "NotUsed_126", /* 127 */ "NotUsed_127", @@ -17111,11 +17740,12 @@ typedef struct os2File os2File; struct os2File { const sqlite3_io_methods *pMethod; /* Always the first entry */ HFILE h; /* Handle for accessing the file */ - int delOnClose; /* True if file is to be deleted on close */ - char* pathToDel; /* Name of file to delete on close */ + char* pathToDel; /* Name of file to delete on close, NULL if not */ unsigned char locktype; /* Type of lock currently held on this file */ }; +#define LOCK_TIMEOUT 10L /* the default locking timeout */ + /***************************************************************************** ** The next group of routines implement the I/O methods specified ** by the sqlite3_io_methods object. @@ -17131,11 +17761,10 @@ int os2Close( sqlite3_file *id ){ OSTRACE2( "CLOSE %d\n", pFile->h ); rc = DosClose( pFile->h ); pFile->locktype = NO_LOCK; - if( pFile->delOnClose != 0 ){ + if( pFile->pathToDel != NULL ){ rc = DosForceDelete( (PSZ)pFile->pathToDel ); - } - if( pFile->pathToDel ){ free( pFile->pathToDel ); + pFile->pathToDel = NULL; } id = 0; OpenCounter( -1 ); @@ -17198,7 +17827,7 @@ int os2Write( } assert( amt>0 ); while( amt > 0 && - (rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote )) && + ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR && wrote > 0 ){ amt -= wrote; @@ -17275,7 +17904,7 @@ static int getReadLock( os2File *pFile ){ LockArea.lRange = SHARED_SIZE; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; - res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L ); OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res ); return res; } @@ -17293,7 +17922,7 @@ static int unlockReadLock( os2File *id ){ LockArea.lRange = 0L; UnlockArea.lOffset = SHARED_FIRST; UnlockArea.lRange = SHARED_SIZE; - res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L ); OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ); return res; } @@ -17339,7 +17968,7 @@ int os2Lock( sqlite3_file *id, int locktype ){ /* If there is already a lock of this type or more restrictive on the ** os2File, do nothing. Don't use the end_lock: exit path, as - ** sqlite3OsEnterMutex() hasn't been called yet. + ** sqlite3_mutex_enter() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype ); @@ -17360,23 +17989,14 @@ int os2Lock( sqlite3_file *id, int locktype ){ if( pFile->locktype==NO_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) ){ - int cnt = 3; - LockArea.lOffset = PENDING_BYTE; LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; - while( cnt-->0 && ( res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) ) - != NO_ERROR - ){ - /* Try 3 times to get the pending lock. The pending lock might be - ** held by another reader process who will release it momentarily. - */ - OSTRACE2( "LOCK could not get a PENDING lock. cnt=%d\n", cnt ); - DosSleep(1); - } - if( res == NO_ERROR){ + /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */ + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L ); + if( res == NO_ERROR ){ gotPendingLock = 1; OSTRACE3( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res ); } @@ -17401,7 +18021,7 @@ int os2Lock( sqlite3_file *id, int locktype ){ LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; - res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); if( res == NO_ERROR ){ newLocktype = RESERVED_LOCK; } @@ -17426,7 +18046,7 @@ int os2Lock( sqlite3_file *id, int locktype ){ LockArea.lRange = SHARED_SIZE; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; - res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); if( res == NO_ERROR ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -17445,7 +18065,7 @@ int os2Lock( sqlite3_file *id, int locktype ){ LockArea.lRange = 0L; UnlockArea.lOffset = PENDING_BYTE; UnlockArea.lRange = 1L; - r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ); } @@ -17486,7 +18106,7 @@ int os2CheckReservedLock( sqlite3_file *id ){ LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; - rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ); if( rc == NO_ERROR ){ APIRET rcu = NO_ERROR; /* return code for unlocking */ @@ -17494,7 +18114,7 @@ int os2CheckReservedLock( sqlite3_file *id ){ LockArea.lRange = 0L; UnlockArea.lOffset = RESERVED_BYTE; UnlockArea.lRange = 1L; - rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ); } r = !(rc == NO_ERROR); @@ -17532,7 +18152,7 @@ int os2Unlock( sqlite3_file *id, int locktype ){ LockArea.lRange = 0L; UnlockArea.lOffset = SHARED_FIRST; UnlockArea.lRange = SHARED_SIZE; - res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ); if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){ /* This should never happen. We should always be able to @@ -17546,7 +18166,7 @@ int os2Unlock( sqlite3_file *id, int locktype ){ LockArea.lRange = 0L; UnlockArea.lOffset = RESERVED_BYTE; UnlockArea.lRange = 1L; - res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "UNLOCK %d reserved res=%d\n", pFile->h, res ); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ @@ -17558,7 +18178,7 @@ int os2Unlock( sqlite3_file *id, int locktype ){ LockArea.lRange = 0L; UnlockArea.lOffset = PENDING_BYTE; UnlockArea.lRange = 1L; - res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L ); OSTRACE3( "UNLOCK %d pending res=%d\n", pFile->h, res ); } pFile->locktype = locktype; @@ -17602,6 +18222,66 @@ static int os2DeviceCharacteristics(sqlite3_file *id){ } /* +** Helper function to convert UTF-8 filenames to local OS/2 codepage. +** The two-step process: first convert the incoming UTF-8 string +** into UCS-2 and then from UCS-2 to the current codepage. +** The returned char pointer has to be freed. +*/ +char *convertUtf8PathToCp(const char *in) +{ + UconvObject uconv; + UniChar ucsUtf8Cp[12], + tempPath[CCHMAXPATH]; + char *out; + int rc = 0; + + out = (char *)calloc(CCHMAXPATH, 1); + + /* determine string for the conversion of UTF-8 which is CP1208 */ + rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12); + rc = UniCreateUconvObject(ucsUtf8Cp, &uconv); + rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH); + rc = UniFreeUconvObject(uconv); + + /* conversion for current codepage which can be used for paths */ + rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv); + rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH); + rc = UniFreeUconvObject(uconv); + + return out; +} + +/* +** Helper function to convert filenames from local codepage to UTF-8. +** The two-step process: first convert the incoming codepage-specific +** string into UCS-2 and then from UCS-2 to the codepage of UTF-8. +** The returned char pointer has to be freed. +*/ +char *convertCpPathToUtf8(const char *in) +{ + UconvObject uconv; + UniChar ucsUtf8Cp[12], + tempPath[CCHMAXPATH]; + char *out; + int rc = 0; + + out = (char *)calloc(CCHMAXPATH, 1); + + /* conversion for current codepage which can be used for paths */ + rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv); + rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH); + rc = UniFreeUconvObject(uconv); + + /* determine string for the conversion of UTF-8 which is CP1208 */ + rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12); + rc = UniCreateUconvObject(ucsUtf8Cp, &uconv); + rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH); + rc = UniFreeUconvObject(uconv); + + return out; +} + +/* ** This vector defines all the methods that can operate on an ** sqlite3_file for os2. */ @@ -17645,7 +18325,7 @@ static int os2Open( APIRET rc = NO_ERROR; ULONG ulAction; - memset(pFile, 0, sizeof(*pFile)); + memset( pFile, 0, sizeof(*pFile) ); OSTRACE2( "OPEN want %d\n", flags ); @@ -17678,15 +18358,14 @@ static int os2Open( if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_SUBJOURNAL) ){ + char pathUtf8[CCHMAXPATH]; //ulFileAttribute = FILE_HIDDEN; //for debugging, we want to make sure it is deleted ulFileAttribute = FILE_NORMAL; - pFile->delOnClose = 1; - pFile->pathToDel = (char*)malloc(sizeof(char) * pVfs->mxPathname); - sqlite3OsFullPathname(pVfs, zName, pVfs->mxPathname, pFile->pathToDel); + sqlite3OsFullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 ); + pFile->pathToDel = convertUtf8PathToCp( pathUtf8 ); OSTRACE1( "OPEN hidden/delete on close file attributes\n" ); }else{ ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL; - pFile->delOnClose = 0; pFile->pathToDel = NULL; OSTRACE1( "OPEN normal file attribute\n" ); } @@ -17694,8 +18373,10 @@ static int os2Open( /* always open in random access mode for possibly better speed */ ulOpenMode |= OPEN_FLAGS_RANDOM; ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR; + ulOpenMode |= OPEN_FLAGS_NOINHERIT; - rc = DosOpen( (PSZ)zName, + char *zNameCp = convertUtf8PathToCp( zName ); + rc = DosOpen( (PSZ)zNameCp, &h, &ulAction, 0L, @@ -17703,9 +18384,12 @@ static int os2Open( ulOpenFlags, ulOpenMode, (PEAOP2)NULL ); + free( zNameCp ); if( rc != NO_ERROR ){ OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n", rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ); + free( pFile->pathToDel ); + pFile->pathToDel = NULL; if( flags & SQLITE_OPEN_READWRITE ){ OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ); return os2Open( 0, zName, id, @@ -17737,7 +18421,9 @@ int os2Delete( ){ APIRET rc = NO_ERROR; SimulateIOError(return SQLITE_IOERR_DELETE); - rc = DosDelete( (PSZ)zFilename ); + char *zFilenameCp = convertUtf8PathToCp( zFilename ); + rc = DosDelete( (PSZ)zFilenameCp ); + free( zFilenameCp ); OSTRACE2( "DELETE \"%s\"\n", zFilename ); return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; } @@ -17753,9 +18439,11 @@ static int os2Access( FILESTATUS3 fsts3ConfigInfo; APIRET rc = NO_ERROR; - memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo)); - rc = DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD, + memset( &fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo) ); + char *zFilenameCp = convertUtf8PathToCp( zFilename ); + rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD, &fsts3ConfigInfo, sizeof(FILESTATUS3) ); + free( zFilenameCp ); OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n", fsts3ConfigInfo.attrFile, flags, rc ); switch( flags ){ @@ -17787,6 +18475,7 @@ static int os2GetTempname( sqlite3_vfs *pVfs, int nBuf, char *zBuf ){ int i, j; char zTempPathBuf[3]; PSZ zTempPath = (PSZ)&zTempPathBuf; + char *zTempPathUTF; if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){ if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){ if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){ @@ -17803,10 +18492,12 @@ static int os2GetTempname( sqlite3_vfs *pVfs, int nBuf, char *zBuf ){ j--; } zTempPath[j] = '\0'; + zTempPathUTF = convertCpPathToUtf8( zTempPath ); sqlite3_snprintf( nBuf-30, zBuf, - "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath ); + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPathUTF ); + free( zTempPathUTF ); j = strlen( zBuf ); - sqlite3Randomness( 20, &zBuf[j] ); + sqlite3_randomness( 20, &zBuf[j] ); for( i = 0; i < 20; i++, j++ ){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } @@ -17827,7 +18518,15 @@ static int os2FullPathname( int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */ ){ - APIRET rc = DosQueryPathInfo( zRelative, FIL_QUERYFULLNAME, zFull, nFull ); + char *zRelativeCp = convertUtf8PathToCp( zRelative ); + char zFullCp[CCHMAXPATH]; + char *zFullUTF; + APIRET rc = DosQueryPathInfo( zRelativeCp, FIL_QUERYFULLNAME, zFullCp, + CCHMAXPATH ); + free( zRelativeCp ); + zFullUTF = convertCpPathToUtf8( zFullCp ); + sqlite3_snprintf( nFull, zFull, zFullUTF ); + free( zFullUTF ); return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; } @@ -17844,7 +18543,9 @@ static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){ UCHAR loadErr[256]; HMODULE hmod; APIRET rc; - rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilename, &hmod); + char *zFilenameCp = convertUtf8PathToCp(zFilename); + rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilenameCp, &hmod); + free(zFilenameCp); return rc != NO_ERROR ? 0 : (void*)hmod; } /* @@ -18784,7 +19485,7 @@ static sqlite3LockingStyle sqlite3DetectLockingStyle( ** describes that file descriptor. Create new ones if necessary. The ** return values might be uninitialized if an error occurs. ** -** Return the number of errors. +** Return an appropriate error code. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ @@ -18798,7 +19499,12 @@ static int findLockInfo( struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); - if( rc!=0 ) return 1; + if( rc!=0 ){ +#ifdef EOVERFLOW + if( errno==EOVERFLOW ) return SQLITE_NOLFS; +#endif + return SQLITE_IOERR; + } memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; @@ -18817,7 +19523,7 @@ static int findLockInfo( struct lockInfo *pOld; pLock = sqlite3_malloc( sizeof(*pLock) ); if( pLock==0 ){ - rc = 1; + rc = SQLITE_NOMEM; goto exit_findlockinfo; } pLock->key = key1; @@ -18828,7 +19534,7 @@ static int findLockInfo( if( pOld!=0 ){ assert( pOld==pLock ); sqlite3_free(pLock); - rc = 1; + rc = SQLITE_NOMEM; goto exit_findlockinfo; } }else{ @@ -18842,7 +19548,7 @@ static int findLockInfo( pOpen = sqlite3_malloc( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); - rc = 1; + rc = SQLITE_NOMEM; goto exit_findlockinfo; } pOpen->key = key2; @@ -18855,7 +19561,7 @@ static int findLockInfo( assert( pOld==pOpen ); sqlite3_free(pOpen); releaseLockInfo(pLock); - rc = 1; + rc = SQLITE_NOMEM; goto exit_findlockinfo; } }else{ @@ -20356,7 +21062,7 @@ static int fillInUnixFile( if( rc ){ if( dirfd>=0 ) close(dirfd); close(h); - return SQLITE_NOMEM; + return rc; } } else { /* pLock and pOpen are only used for posix advisory locking */ @@ -20445,7 +21151,7 @@ static int fillInUnixFile( if( rc ){ if( dirfd>=0 ) close(dirfd); close(h); - return SQLITE_NOMEM; + return rc; } OSTRACE3("OPEN %-3d %s\n", h, zFilename); @@ -20687,14 +21393,19 @@ static int unixGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ zDir = azDirs[i]; break; } - if( strlen(zDir) - sizeof(SQLITE_TEMP_FILE_PREFIX) - 17 <=0 ){ + + /* Check that the output buffer is large enough for the temporary file + ** name. If it is not, return SQLITE_ERROR. + */ + if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){ return SQLITE_ERROR; } + do{ assert( pVfs->mxPathname==MAX_PATHNAME ); sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); j = strlen(zBuf); - sqlite3Randomness(15, &zBuf[j]); + sqlite3_randomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } @@ -21849,7 +22560,7 @@ static int getReadLock(winFile *pFile){ 0, SHARED_SIZE, 0, &ovlp); }else{ int lk; - sqlite3Randomness(sizeof(lk), &lk); + sqlite3_randomness(sizeof(lk), &lk); pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); } @@ -22383,7 +23094,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ sqlite3_snprintf(nBuf-30, zBuf, "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); j = strlen(zBuf); - sqlite3Randomness(20, &zBuf[j]); + sqlite3_randomness(20, &zBuf[j]); for(i=0; i<20; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } @@ -22669,13 +23380,13 @@ SQLITE_PRIVATE sqlite3_vfs *sqlite3OsDefaultVfs(void){ ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. ** -** @(#) $Id: bitvec.c,v 1.2 2008/03/14 13:02:08 mlcreech Exp $ +** @(#) $Id: bitvec.c,v 1.5 2008/05/13 13:27:34 drh Exp $ */ #define BITVEC_SZ 512 /* Round the union size down to the nearest pointer boundary, since that's how ** it will be aligned within the Bitvec struct. */ -#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec *))*sizeof(Bitvec *)) +#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*)) #define BITVEC_NCHAR BITVEC_USIZE #define BITVEC_NBIT (BITVEC_NCHAR*8) #define BITVEC_NINT (BITVEC_USIZE/4) @@ -22737,9 +23448,8 @@ SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){ ** i is out of range, then return false. */ SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ - assert( i>0 ); if( p==0 ) return 0; - if( i>p->iSize ) return 0; + if( i>p->iSize || i==0 ) return 0; if( p->iSize<=BITVEC_NBIT ){ i--; return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0; @@ -22766,6 +23476,8 @@ SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ u32 h; assert( p!=0 ); + assert( i>0 ); + assert( i<=p->iSize ); if( p->iSize<=BITVEC_NBIT ){ i--; p->u.aBitmap[i/8] |= 1 << (i&7); @@ -22775,9 +23487,9 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ u32 bin = (i-1)/p->iDivisor; i = (i-1)%p->iDivisor + 1; if( p->u.apSub[bin]==0 ){ - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1); + sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC); p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC); if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; } return sqlite3BitvecSet(p->u.apSub[bin], i); @@ -22795,8 +23507,8 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){ memcpy(aiValues, p->u.aHash, sizeof(aiValues)); memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR); p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; - sqlite3BitvecSet(p, i); - for(rc=j=0; j0 ); if( p->iSize<=BITVEC_NBIT ){ i--; p->u.aBitmap[i/8] &= ~(1 << (i&7)); @@ -22827,7 +23540,9 @@ SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){ memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT); p->nSet = 0; for(j=0; j>3] |= (1<<(I&7)) +#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7)) +#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0 + +/* +** This routine runs an extensive test of the Bitvec code. +** +** The input is an array of integers that acts as a program +** to test the Bitvec. The integers are opcodes followed +** by 0, 1, or 3 operands, depending on the opcode. Another +** opcode follows immediately after the last operand. +** +** There are 6 opcodes numbered from 0 through 5. 0 is the +** "halt" opcode and causes the test to end. +** +** 0 Halt and return the number of errors +** 1 N S X Set N bits beginning with S and incrementing by X +** 2 N S X Clear N bits beginning with S and incrementing by X +** 3 N Set N randomly chosen bits +** 4 N Clear N randomly chosen bits +** 5 N S X Set N bits from S increment X in array only, not in bitvec +** +** The opcodes 1 through 4 perform set and clear operations are performed +** on both a Bitvec object and on a linear array of bits obtained from malloc. +** Opcode 5 works on the linear array only, not on the Bitvec. +** Opcode 5 is used to deliberately induce a fault in order to +** confirm that error detection works. +** +** At the conclusion of the test the linear array is compared +** against the Bitvec object. If there are any differences, +** an error is returned. If they are the same, zero is returned. +** +** If a memory allocation error occurs, return -1. +*/ +SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){ + Bitvec *pBitvec = 0; + unsigned char *pV = 0; + int rc = -1; + int i, nx, pc, op; + + /* Allocate the Bitvec to be tested and a linear array of + ** bits to act as the reference */ + pBitvec = sqlite3BitvecCreate( sz ); + pV = sqlite3_malloc( (sz+7)/8 + 1 ); + if( pBitvec==0 || pV==0 ) goto bitvec_end; + memset(pV, 0, (sz+7)/8 + 1); + + /* Run the program */ + pc = 0; + while( (op = aOp[pc])!=0 ){ + switch( op ){ + case 1: + case 2: + case 5: { + nx = 4; + i = aOp[pc+2] - 1; + aOp[pc+2] += aOp[pc+3]; + break; + } + case 3: + case 4: + default: { + nx = 2; + sqlite3_randomness(sizeof(i), &i); + break; + } + } + if( (--aOp[pc+1]) > 0 ) nx = 0; + pc += nx; + i = (i & 0x7fffffff)%sz; + if( (op & 1)!=0 ){ + SETBIT(pV, (i+1)); + if( op!=5 ){ + if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end; + } + }else{ + CLEARBIT(pV, (i+1)); + sqlite3BitvecClear(pBitvec, i+1); + } + } + + /* Test to make sure the linear array exactly matches the + ** Bitvec object. Start with the assumption that they do + ** match (rc==0). Change rc to non-zero if a discrepancy + ** is found. + */ + rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1) + + sqlite3BitvecTest(pBitvec, 0); + for(i=1; i<=sz; i++){ + if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){ + rc = i; + break; + } + } + + /* Free allocated structure */ +bitvec_end: + sqlite3_free(pV); + sqlite3BitvecDestroy(pBitvec); + return rc; +} +#endif /* SQLITE_OMIT_BUILTIN_TEST */ + /************** End of bitvec.c **********************************************/ /************** Begin file pager.c *******************************************/ /* @@ -22868,7 +23693,7 @@ SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.417 2008/03/17 13:50:58 drh Exp $ +** @(#) $Id: pager.c,v 1.446 2008/05/13 13:27:34 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO @@ -23197,6 +24022,8 @@ struct Pager { u8 setMaster; /* True if a m-j name has been written to jrnl */ u8 doNotSync; /* Boolean. While true, do not spill the cache */ u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ + u8 journalMode; /* On of the PAGER_JOURNALMODE_* values */ + u8 dbModified; /* True if there are any changes to the Db */ u8 changeCountDone; /* Set after incrementing the change-counter */ u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ int errCode; /* One of several kinds of errors */ @@ -23361,8 +24188,10 @@ static const unsigned char aJournalMagic[] = { static void pagerEnter(Pager *p){ p->iInUseDB++; if( p->iInUseMM && p->iInUseDB==1 ){ +#ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex; mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); +#endif p->iInUseDB = 0; sqlite3_mutex_enter(mutex); p->iInUseDB = 1; @@ -23531,9 +24360,9 @@ static void pager_resize_hash_table(Pager *pPager, int N){ if( N==pPager->nHash ) return; #endif pagerLeave(pPager); - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pPager->aHash!=0); + if( pPager->aHash!=0 ) sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC); aHash = sqlite3MallocZero( sizeof(aHash[0])*N ); - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + if( pPager->aHash!=0 ) sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC); pagerEnter(pPager); if( aHash==0 ){ /* Failure to rehash is not an error. It is only a performance hit. */ @@ -23808,6 +24637,29 @@ static void seekJournalHdr(Pager *pPager){ } /* +** Write zeros over the header of the journal file. This has the +** effect of invalidating the journal file and committing the +** transaction. +*/ +static int zeroJournalHdr(Pager *pPager, int doTruncate){ + int rc = SQLITE_OK; + static const char zeroHdr[28]; + + if( pPager->journalOff ){ + IOTRACE(("JZEROHDR %p\n", pPager)) + if( doTruncate ){ + rc = sqlite3OsTruncate(pPager->jfd, 0); + }else{ + rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->sync_flags); + } + } + return rc; +} + +/* ** The journal file must be open when this routine is called. A journal ** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the ** current location. @@ -23818,12 +24670,19 @@ static void seekJournalHdr(Pager *pPager){ ** - 4 bytes: Random number used for page hash. ** - 4 bytes: Initial database page count. ** - 4 bytes: Sector size used by the process that wrote this journal. +** - 4 bytes: Database page size. ** -** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space. +** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space. */ static int writeJournalHdr(Pager *pPager){ - char zHeader[sizeof(aJournalMagic)+16]; - int rc; + int rc = SQLITE_OK; + char *zHeader = pPager->pTmpSpace; + int nHeader = pPager->pageSize; + int nWrite; + + if( nHeader>JOURNAL_HDR_SZ(pPager) ){ + nHeader = JOURNAL_HDR_SZ(pPager); + } if( pPager->stmtHdrOff==0 ){ pPager->stmtHdrOff = pPager->journalOff; @@ -23864,23 +24723,23 @@ static int writeJournalHdr(Pager *pPager){ } /* The random check-hash initialiser */ - sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); /* The initial database size */ put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize); /* The assumed sector size for this process */ put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); - IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader))) - rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff); - pPager->journalOff += JOURNAL_HDR_SZ(pPager); + if( pPager->journalHdr==0 ){ + /* The page size */ + put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize); + } - /* The journal header has been written successfully. Seek the journal - ** file descriptor to the end of the journal header sector. - */ - if( rc==SQLITE_OK ){ - IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1)) - rc = sqlite3OsWrite(pPager->jfd, "\000", 1, pPager->journalOff-1); + for(nWrite=0; rc==SQLITE_OK&&nWritejournalHdr, nHeader)) + rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff); + pPager->journalOff += nHeader; } + return rc; } @@ -23909,6 +24768,7 @@ static int readJournalHdr( int rc; unsigned char aMagic[8]; /* A buffer to hold the magic header */ i64 jrnlOff; + int iPageSize; seekJournalHdr(pPager); if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ @@ -23933,6 +24793,17 @@ static int readJournalHdr( rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize); if( rc ) return rc; + rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize); + if( rc==SQLITE_OK + && iPageSize>=512 + && iPageSize<=SQLITE_MAX_PAGE_SIZE + && ((iPageSize-1)&iPageSize)==0 + ){ + u16 pagesize = iPageSize; + rc = sqlite3PagerSetPagesize(pPager, &pagesize); + } + if( rc ) return rc; + /* Update the assumed sector-size to match the value used by ** the process that created this journal. If this journal was ** created by a process other than this one, then this routine @@ -23971,6 +24842,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ int len; int i; i64 jrnlOff; + i64 jrnlSize; u32 cksum = 0; char zBuf[sizeof(aJournalMagic)+2*4]; @@ -24004,7 +24876,25 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){ put32bits(&zBuf[4], cksum); memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic)); rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff); + jrnlOff += 8+sizeof(aJournalMagic); pPager->needSync = !pPager->noSync; + + /* If the pager is in peristent-journal mode, then the physical + ** journal-file may extend past the end of the master-journal name + ** and 8 bytes of magic data just written to the file. This is + ** dangerous because the code to rollback a hot-journal file + ** will not be able to find the master-journal name to determine + ** whether or not the journal is hot. + ** + ** Easiest thing to do in this scenario is to truncate the journal + ** file to the required size. + */ + if( (rc==SQLITE_OK) + && (rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))==SQLITE_OK + && jrnlSize>jrnlOff + ){ + rc = sqlite3OsTruncate(pPager->jfd, jrnlOff); + } return rc; } @@ -24093,6 +24983,17 @@ static void pager_unlock(Pager *pPager){ pPager->dbSize = -1; IOTRACE(("UNLOCK %p\n", pPager)) + /* Always close the journal file when dropping the database lock. + ** Otherwise, another connection with journal_mode=delete might + ** delete the file out from under us. + */ + if( pPager->journalOpen ){ + sqlite3OsClose(pPager->jfd); + pPager->journalOpen = 0; + sqlite3BitvecDestroy(pPager->pInJournal); + pPager->pInJournal = 0; + } + /* If Pager.errCode is set, the contents of the pager cache cannot be ** trusted. Now that the pager file is unlocked, the contents of the ** cache can be discarded and the error code safely cleared. @@ -24105,12 +25006,6 @@ static void pager_unlock(Pager *pPager){ sqlite3BitvecDestroy(pPager->pInStmt); pPager->pInStmt = 0; } - if( pPager->journalOpen ){ - sqlite3OsClose(pPager->jfd); - pPager->journalOpen = 0; - sqlite3BitvecDestroy(pPager->pInJournal); - pPager->pInJournal = 0; - } pPager->stmtOpen = 0; pPager->stmtInUse = 0; pPager->journalOff = 0; @@ -24133,13 +25028,17 @@ static void pager_unlock(Pager *pPager){ ** do not attempt the rollback. */ static void pagerUnlockAndRollback(Pager *p){ - assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); + /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */ if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){ + sqlite3FaultBeginBenign(-1); sqlite3PagerRollback(p); + sqlite3FaultEndBenign(-1); } pager_unlock(p); +#if 0 assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) ); assert( p->errCode || !p->stmtOpen || p->exclusiveMode ); +#endif } /* @@ -24159,7 +25058,7 @@ static void pagerUnlockAndRollback(Pager *p){ ** This might give a performance improvement on windows where opening ** a file is an expensive operation. */ -static int pager_end_transaction(Pager *pPager){ +static int pager_end_transaction(Pager *pPager, int hasMaster){ PgHdr *pPg; int rc = SQLITE_OK; int rc2 = SQLITE_OK; @@ -24174,7 +25073,10 @@ static int pager_end_transaction(Pager *pPager){ } if( pPager->journalOpen ){ if( pPager->exclusiveMode - && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){; + || pPager->journalMode==PAGER_JOURNALMODE_PERSIST + ){ + rc = zeroJournalHdr(pPager, hasMaster); + pager_error(pPager, rc); pPager->journalOff = 0; pPager->journalStarted = 0; }else{ @@ -24200,7 +25102,6 @@ static int pager_end_transaction(Pager *pPager){ pPager->nRec = 0; }else{ assert( pPager->pInJournal==0 ); - assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); } if( !pPager->exclusiveMode ){ @@ -24214,6 +25115,7 @@ static int pager_end_transaction(Pager *pPager){ pPager->needSync = 0; lruListSetFirstSynced(pPager); pPager->dbSize = -1; + pPager->dbModified = 0; return (rc==SQLITE_OK?rc2:rc); } @@ -24332,11 +25234,16 @@ static int pager_playback_one_page( ** locked. (2) we know that the original page content is fully synced ** in the main journal either because the page is not in cache or else ** the page is marked as needSync==0. + ** + ** 2008-04-14: When attempting to vacuum a corrupt database file, it + ** is possible to fail a statement on a database that does not yet exist. + ** Do not attempt to write if database file has never been opened. */ pPg = pager_lookup(pPager, pgno); PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n", PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData)); - if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ + if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) + && pPager->fd->pMethods ){ i64 offset = (pgno-1)*(i64)pPager->pageSize; rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset); if( pPg ){ @@ -24432,7 +25339,12 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){ zJournal = zMasterJournal; while( (zJournal-zMasterJournal)fd, ¤tSize); newSize = pPager->pageSize*(i64)nPage; - if( rc==SQLITE_OK && currentSize>newSize ){ - rc = sqlite3OsTruncate(pPager->fd, newSize); + if( rc==SQLITE_OK && currentSize!=newSize ){ + if( currentSize>newSize ){ + rc = sqlite3OsTruncate(pPager->fd, newSize); + }else{ + rc = sqlite3OsWrite(pPager->fd, "", 1, newSize-1); + } } } if( rc==SQLITE_OK ){ @@ -24508,8 +25425,8 @@ static int pager_truncate(Pager *pPager, int nPage){ /* ** Set the sectorSize for the given pager. ** -** The sector size is the larger of the sector size reported -** by sqlite3OsSectorSize() and the pageSize. +** The sector size is at least as big as the sector size reported +** by sqlite3OsSectorSize(). The minimum sector size is 512. */ static void setSectorSize(Pager *pPager){ assert(pPager->fd->pMethods||pPager->tempFile); @@ -24520,8 +25437,8 @@ static void setSectorSize(Pager *pPager){ */ pPager->sectorSize = sqlite3OsSectorSize(pPager->fd); } - if( pPager->sectorSizepageSize ){ - pPager->sectorSize = pPager->pageSize; + if( pPager->sectorSize<512 ){ + pPager->sectorSize = 512; } } @@ -24539,20 +25456,23 @@ static void setSectorSize(Pager *pPager){ ** sanity checksum. ** (4) 4 byte integer which is the number of pages to truncate the ** database to during a rollback. -** (5) 4 byte integer which is the number of bytes in the master journal +** (5) 4 byte big-endian integer which is the sector size. The header +** is this many bytes in size. +** (6) 4 byte big-endian integer which is the page case. +** (7) 4 byte integer which is the number of bytes in the master journal ** name. The value may be zero (indicate that there is no master ** journal.) -** (6) N bytes of the master journal name. The name will be nul-terminated +** (8) N bytes of the master journal name. The name will be nul-terminated ** and might be shorter than the value read from (5). If the first byte ** of the name is \000 then there is no master journal. The master ** journal name is stored in UTF-8. -** (7) Zero or more pages instances, each as follows: +** (9) Zero or more pages instances, each as follows: ** + 4 byte page number. ** + pPager->pageSize bytes of data. ** + 4 byte checksum ** -** When we speak of the journal header, we mean the first 6 items above. -** Each entry in the journal is an instance of the 7th item. +** When we speak of the journal header, we mean the first 8 items above. +** Each entry in the journal is an instance of the 9th item. ** ** Call the value from the second bullet "nRec". nRec is the number of ** valid page entries in the journal. In most cases, you can compute the @@ -24585,6 +25505,7 @@ static int pager_playback(Pager *pPager, int isHot){ int i; /* Loop counter */ Pgno mxPg = 0; /* Size of the original file in pages */ int rc; /* Result code of a subroutine */ + int res = 0; /* Value returned by sqlite3OsAccess() */ char *zMaster = 0; /* Name of master journal file if any */ /* Figure out how many records are in the journal. Abort early if @@ -24603,16 +25524,18 @@ static int pager_playback(Pager *pPager, int isHot){ */ zMaster = pPager->pTmpSpace; rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); - assert( rc!=SQLITE_DONE ); - if( rc!=SQLITE_OK - || (zMaster[0] && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS)) + if( rc!=SQLITE_OK || (zMaster[0] + && (res=sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS))==0 ) ){ zMaster = 0; - if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } - pPager->journalOff = 0; zMaster = 0; + if( res<0 ){ + rc = SQLITE_IOERR_NOMEM; + goto end_playback; + } + pPager->journalOff = 0; /* This loop terminates either when the readJournalHdr() call returns ** SQLITE_DONE or an IO error occurs. */ @@ -24688,7 +25611,7 @@ end_playback: rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); } if( rc==SQLITE_OK ){ - rc = pager_end_transaction(pPager); + rc = pager_end_transaction(pPager, zMaster[0]!='\0'); } if( rc==SQLITE_OK && zMaster[0] ){ /* If there was a master journal and this routine will return success, @@ -24727,14 +25650,6 @@ static int pager_stmt_playback(Pager *pPager){ int rc; szJ = pPager->journalOff; -#ifndef NDEBUG - { - i64 os_szJ; - rc = sqlite3OsFileSize(pPager->jfd, &os_szJ); - if( rc!=SQLITE_OK ) return rc; - assert( szJ==os_szJ ); - } -#endif /* Set hdrOff to be the offset just after the end of the last journal ** page written before the first journal-header for this statement @@ -25051,7 +25966,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( } if( pPager && rc==SQLITE_OK ){ - pPager->pTmpSpace = (char *)sqlite3_malloc(nDefaultPage); + pPager->pTmpSpace = sqlite3MallocZero(nDefaultPage); } /* If an error occured in either of the blocks above. @@ -25119,7 +26034,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( pPager->iInUseMM = 0; pPager->iInUseDB = 0; if( !memDb ){ +#ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); +#endif sqlite3_mutex_enter(mutex); pPager->pNext = sqlite3PagerList; if( sqlite3PagerList ){ @@ -25501,7 +26418,9 @@ SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( !MEMDB ){ +#ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); +#endif sqlite3_mutex_enter(mutex); if( pPager->pPrev ){ pPager->pPrev->pNext = pPager->pNext; @@ -25516,14 +26435,15 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ #endif disable_simulated_io_errors(); + sqlite3FaultBeginBenign(-1); pPager->errCode = 0; pPager->exclusiveMode = 0; pager_reset(pPager); pagerUnlockAndRollback(pPager); enable_simulated_io_errors(); + sqlite3FaultEndBenign(-1); PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); IOTRACE(("CLOSE %p\n", pPager)) - assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); if( pPager->journalOpen ){ sqlite3OsClose(pPager->jfd); } @@ -25631,19 +26551,6 @@ static int syncJournal(Pager *pPager){ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); assert( pPager->journalOpen ); - /* assert( !pPager->noSync ); // noSync might be set if synchronous - ** was turned off after the transaction was started. Ticket #615 */ -#ifndef NDEBUG - { - /* Make sure the pPager->nRec counter we are keeping agrees - ** with the nRec computed from the size of the journal file. - */ - i64 jSz; - rc = sqlite3OsFileSize(pPager->jfd, &jSz); - if( rc!=0 ) return rc; - assert( pPager->journalOff==jSz ); - } -#endif if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ /* Write the nRec value into the journal file header. If in ** full-synchronous mode, sync the journal first. This ensures that @@ -25883,19 +26790,32 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ } /* -** Return TRUE if there is a hot journal on the given pager. +** Return 1 if there is a hot journal on the given pager. ** A hot journal is one that needs to be played back. ** ** If the current size of the database file is 0 but a journal file ** exists, that is probably an old journal left over from a prior ** database with the same name. Just delete the journal. +** +** Return negative if unable to determine the status of the journal. +** +** This routine does not open the journal file to examine its +** content. Hence, the journal might contain the name of a master +** journal file that has been deleted, and hence not be hot. Or +** the header of the journal might be zeroed out. This routine +** does not discover these cases of a non-hot journal - if the +** journal file exists and is not empty this routine assumes it +** is hot. The pager_playback() routine will discover that the +** journal file is not really hot and will no-op. */ static int hasHotJournal(Pager *pPager){ sqlite3_vfs *pVfs = pPager->pVfs; + int rc; if( !pPager->useJournal ) return 0; if( !pPager->fd->pMethods ) return 0; - if( !sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){ - return 0; + rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS); + if( rc<=0 ){ + return rc; } if( sqlite3OsCheckReservedLock(pPager->fd) ){ return 0; @@ -26010,14 +26930,16 @@ static int pager_recycle(Pager *pPager, PgHdr **ppPg){ */ SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int nReq){ int nReleased = 0; /* Bytes of memory released so far */ - sqlite3_mutex *mutex; /* The MEM2 mutex */ Pager *pPager; /* For looping over pagers */ BusyHandler *savedBusy; /* Saved copy of the busy handler */ int rc = SQLITE_OK; /* Acquire the memory-management mutex */ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex; /* The MEM2 mutex */ mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); +#endif sqlite3_mutex_enter(mutex); /* Signal all database connections that memory management wants @@ -26168,8 +27090,8 @@ static int pagerSharedLock(Pager *pPager){ if( pPager->journalOpen ){ isHot = 1; } - pager_reset(pPager); pPager->errCode = SQLITE_OK; + pager_reset(pPager); } /* If the pager is still in an error state, do not proceed. The error @@ -26187,6 +27109,7 @@ static int pagerSharedLock(Pager *pPager){ if( !pPager->noReadlock ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ + assert( pPager->state==PAGER_UNLOCK ); return pager_error(pPager, rc); } assert( pPager->state>=SHARED_LOCK ); @@ -26195,7 +27118,12 @@ static int pagerSharedLock(Pager *pPager){ /* If a journal file exists, and there is no RESERVED lock on the ** database file, then it either needs to be played back or deleted. */ - if( hasHotJournal(pPager) || isHot ){ + rc = hasHotJournal(pPager); + if( rc<0 ){ + rc = SQLITE_IOERR_NOMEM; + goto failed; + } + if( rc==1 || isHot ){ /* Get an EXCLUSIVE lock on the database file. At this point it is ** important that a RESERVED lock is not obtained on the way to the ** EXCLUSIVE lock. If it were, another process might open the @@ -26210,29 +27138,21 @@ static int pagerSharedLock(Pager *pPager){ if( pPager->statefd, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ - pager_unlock(pPager); - return pager_error(pPager, rc); + rc = pager_error(pPager, rc); + goto failed; } pPager->state = PAGER_EXCLUSIVE; } - /* Open the journal for reading only. Return SQLITE_BUSY if - ** we are unable to open the journal file. - ** - ** The journal file does not need to be locked itself. The - ** journal file is never open unless the main database file holds - ** a write lock, so there is never any chance of two or more - ** processes opening the journal at the same time. - ** - ** Open the journal for read/write access. This is because in + /* Open the journal for read/write access. This is because in ** exclusive-access mode the file descriptor will be kept open and ** possibly used for a transaction later on. On some systems, the ** OsTruncate() call used in exclusive-access mode also requires ** a read/write file handle. */ - if( !isHot ){ - rc = SQLITE_BUSY; - if( sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){ + if( !isHot && pPager->journalOpen==0 ){ + int res = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS); + if( res==1 ){ int fout = 0; int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; assert( !pPager->tempFile ); @@ -26242,18 +27162,23 @@ static int pagerSharedLock(Pager *pPager){ rc = SQLITE_BUSY; sqlite3OsClose(pPager->jfd); } + }else if( res==0 ){ + /* If the journal does not exist, that means some other process + ** has already rolled it back */ + rc = SQLITE_BUSY; + }else{ + /* If sqlite3OsAccess() returns a negative value, that means it + ** failed a memory allocation */ + rc = SQLITE_IOERR_NOMEM; } } if( rc!=SQLITE_OK ){ - pager_unlock(pPager); - switch( rc ){ - case SQLITE_NOMEM: - case SQLITE_IOERR_UNLOCK: - case SQLITE_IOERR_NOMEM: - return rc; - default: - return SQLITE_BUSY; + if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK + && rc!=SQLITE_IOERR_NOMEM + ){ + rc = SQLITE_BUSY; } + goto failed; } pPager->journalOpen = 1; pPager->journalStarted = 0; @@ -26266,7 +27191,8 @@ static int pagerSharedLock(Pager *pPager){ */ rc = pager_playback(pPager, 1); if( rc!=SQLITE_OK ){ - return pager_error(pPager, rc); + rc = pager_error(pPager, rc); + goto failed; } assert(pPager->state==PAGER_SHARED || (pPager->exclusiveMode && pPager->state>PAGER_SHARED) @@ -26294,14 +27220,15 @@ static int pagerSharedLock(Pager *pPager){ sqlite3PagerPagecount(pPager); if( pPager->errCode ){ - return pPager->errCode; + rc = pPager->errCode; + goto failed; } if( pPager->dbSize>0 ){ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); if( rc!=SQLITE_OK ){ - return rc; + goto failed; } }else{ memset(dbFileVers, 0, sizeof(dbFileVers)); @@ -26318,6 +27245,11 @@ static int pagerSharedLock(Pager *pPager){ } } + failed: + if( rc!=SQLITE_OK ){ + /* pager_unlock() is a no-op for exclusive mode and in-memory databases. */ + pager_unlock(pPager); + } return rc; } @@ -26629,7 +27561,10 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ ** removed. */ SQLITE_PRIVATE int sqlite3PagerUnref(DbPage *pPg){ - Pager *pPager = pPg->pPager; + Pager *pPager; + + if( pPg==0 ) return SQLITE_OK; + pPager = pPg->pPager; /* Decrement the reference count for this page */ @@ -26676,7 +27611,6 @@ static int pager_open_journal(Pager *pPager){ int rc; assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); - assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); assert( pPager->pInJournal==0 ); sqlite3PagerPagecount(pPager); @@ -26688,27 +27622,29 @@ static int pager_open_journal(Pager *pPager){ goto failed_to_open_journal; } - if( pPager->tempFile ){ - flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); - }else{ - flags |= (SQLITE_OPEN_MAIN_JOURNAL); - } + if( pPager->journalOpen==0 ){ + if( pPager->tempFile ){ + flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); + }else{ + flags |= (SQLITE_OPEN_MAIN_JOURNAL); + } #ifdef SQLITE_ENABLE_ATOMIC_WRITE - rc = sqlite3JournalOpen( - pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) - ); + rc = sqlite3JournalOpen( + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + ); #else - rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); #endif - assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); - pPager->journalOff = 0; - pPager->setMaster = 0; - pPager->journalHdr = 0; - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ){ - sqlite3OsDelete(pVfs, pPager->zJournal, 0); + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + } + goto failed_to_open_journal; } - goto failed_to_open_journal; } pPager->journalOpen = 1; pPager->journalStarted = 0; @@ -26727,7 +27663,7 @@ static int pager_open_journal(Pager *pPager){ rc = sqlite3PagerStmtBegin(pPager); } if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_NOMEM ){ - rc = pager_end_transaction(pPager); + rc = pager_end_transaction(pPager, 0); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } @@ -26792,15 +27728,17 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){ } pPager->dirtyCache = 0; PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); - if( pPager->useJournal && !pPager->tempFile ){ + if( pPager->useJournal && !pPager->tempFile + && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ rc = pager_open_journal(pPager); } } }else if( pPager->journalOpen && pPager->journalOff==0 ){ - /* This happens when the pager was in exclusive-access mode last + /* This happens when the pager was in exclusive-access mode the last ** time a (read or write) transaction was successfully concluded ** by this connection. Instead of deleting the journal file it was - ** kept open and truncated to 0 bytes. + ** kept open and either was truncated to 0 bytes or its header was + ** overwritten with zeros. */ assert( pPager->nRec==0 ); assert( pPager->origDbSize==0 ); @@ -26914,6 +27852,7 @@ static int pager_write(PgHdr *pPg){ makeDirty(pPg); if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){ pPager->dirtyCache = 1; + pPager->dbModified = 1; }else{ /* If we get this far, it means that the page needs to be @@ -26929,18 +27868,19 @@ static int pager_write(PgHdr *pPg){ return rc; } assert( pPager->state>=PAGER_RESERVED ); - if( !pPager->journalOpen && pPager->useJournal ){ + if( !pPager->journalOpen && pPager->useJournal + && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; } - assert( pPager->journalOpen || !pPager->useJournal ); pPager->dirtyCache = 1; + pPager->dbModified = 1; /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ - if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ + if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){ if( (int)pPg->pgno <= pPager->origDbSize ){ if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); @@ -27156,29 +28096,6 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ } #endif -#ifndef SQLITE_OMIT_VACUUM -/* -** Replace the content of a single page with the information in the third -** argument. -*/ -SQLITE_PRIVATE int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){ - PgHdr *pPg; - int rc; - - pagerEnter(pPager); - rc = sqlite3PagerGet(pPager, pgno, &pPg); - if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(pPg); - if( rc==SQLITE_OK ){ - memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize); - } - sqlite3PagerUnref(pPg); - } - pagerLeave(pPager); - return rc; -} -#endif - /* ** A call to this routine tells the pager that it is not necessary to ** write the information on page pPg back to the disk, even though @@ -27243,19 +28160,6 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){ ** the PgHdr.needRead flag is set) then this routine acts as a promise ** that we will never need to read the page content in the future. ** so the needRead flag can be cleared at this point. -** -** This routine is only called from a single place in the sqlite btree -** code (when a leaf is removed from the free-list). This allows the -** following assumptions to be made about pPg: -** -** 1. PagerDontWrite() has been called on the page, OR -** PagerWrite() has not yet been called on the page. -** -** 2. The page existed when the transaction was started. -** -** Details: DontRollback() (this routine) is only called when a leaf is -** removed from the free list. DontWrite() is called whenever a page -** becomes a free-list leaf. */ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){ Pager *pPager = pPg->pPager; @@ -27273,8 +28177,17 @@ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){ } assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */ - /* Check that PagerWrite() has not yet been called on this page, and - ** that the page existed when the transaction started. +#ifdef SQLITE_SECURE_DELETE + if( pPg->inJournal || (int)pPg->pgno > pPager->origDbSize ){ + return; + } +#endif + + /* If SECURE_DELETE is disabled, then there is no way that this + ** routine can be called on a page for which sqlite3PagerDontWrite() + ** has not been previously called during the same transaction. + ** And if DontWrite() has previously been called, the following + ** conditions must be met. */ assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); @@ -27283,7 +28196,7 @@ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){ pPg->inJournal = 1; pPg->needRead = 0; if( pPager->stmtInUse ){ - assert( pPager->stmtSize <= pPager->origDbSize ); + assert( pPager->stmtSize >= pPager->origDbSize ); sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); } PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); @@ -27332,6 +28245,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){ } /* +** Sync the pager file to disk. +*/ +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){ + int rc; + pagerEnter(pPager); + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + pagerLeave(pPager); + return rc; +} + +/* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual ** journal file. zMaster may be NULL, which is interpreted as no master @@ -27347,10 +28271,29 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){ ** ** If parameter nTrunc is non-zero, then the pager file is truncated to ** nTrunc pages (this is used by auto-vacuum databases). +** +** If the final parameter - noSync - is true, then the database file itself +** is not synced. The caller must call sqlite3PagerSync() directly to +** sync the database file before calling CommitPhaseTwo() to delete the +** journal file in this case. */ -SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( + Pager *pPager, + const char *zMaster, + Pgno nTrunc, + int noSync +){ int rc = SQLITE_OK; + /* If no changes have been made, we can leave the transaction early. + */ + if( pPager->dbModified==0 && + (pPager->journalMode!=PAGER_JOURNALMODE_DELETE || + pPager->exclusiveMode!=0) ){ + assert( pPager->dirtyCache==0 || pPager->journalOpen==0 ); + return SQLITE_OK; + } + PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", pPager->zFilename, zMaster, nTrunc); pagerEnter(pPager); @@ -27375,10 +28318,12 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster */ int useAtomicWrite = ( !zMaster && + pPager->journalOpen && pPager->journalOff==jrnlBufferSize(pPager) && nTrunc==0 && (0==pPager->pDirty || 0==pPager->pDirty->pDirty) ); + assert( pPager->journalOpen || pPager->journalMode==PAGER_JOURNALMODE_OFF ); if( useAtomicWrite ){ /* Update the nRec field in the journal file. */ int offset = pPager->journalHdr + sizeof(aJournalMagic); @@ -27408,7 +28353,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster ** transaction the m-j name will have already been written. */ if( !pPager->setMaster ){ - assert( pPager->journalOpen ); rc = pager_incr_changecounter(pPager, 0); if( rc!=SQLITE_OK ) goto sync_exit; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -27460,7 +28404,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster pPager->pDirty = 0; /* Sync the database file. */ - if( !pPager->noSync ){ + if( !pPager->noSync && !noSync ){ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); } IOTRACE(("DBSYNC %p\n", pPager)) @@ -27501,6 +28445,12 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ if( pPager->statedbModified==0 && + (pPager->journalMode!=PAGER_JOURNALMODE_DELETE || + pPager->exclusiveMode!=0) ){ + assert( pPager->dirtyCache==0 || pPager->journalOpen==0 ); + return SQLITE_OK; + } pagerEnter(pPager); PAGERTRACE2("COMMIT %d\n", PAGERID(pPager)); if( MEMDB ){ @@ -27529,9 +28479,8 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ pagerLeave(pPager); return SQLITE_OK; } - assert( pPager->journalOpen || !pPager->dirtyCache ); assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); - rc = pager_end_transaction(pPager); + rc = pager_end_transaction(pPager, pPager->setMaster); rc = pager_error(pPager, rc); pagerLeave(pPager); return rc; @@ -27590,7 +28539,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ pagerEnter(pPager); if( !pPager->dirtyCache || !pPager->journalOpen ){ - rc = pager_end_transaction(pPager); + rc = pager_end_transaction(pPager, pPager->setMaster); pagerLeave(pPager); return rc; } @@ -27605,7 +28554,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_playback(pPager, 0); - rc2 = pager_end_transaction(pPager); + rc2 = pager_end_transaction(pPager, pPager->setMaster); if( rc==SQLITE_OK ){ rc = rc2; } @@ -27691,11 +28640,6 @@ static int pagerStmtBegin(Pager *pPager){ /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ return SQLITE_NOMEM; } -#ifndef NDEBUG - rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); - if( rc ) goto stmt_begin_failed; - assert( pPager->stmtJSize == pPager->journalOff ); -#endif pPager->stmtJSize = pPager->journalOff; pPager->stmtSize = pPager->dbSize; pPager->stmtHdrOff = 0; @@ -27924,6 +28868,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){ makeDirty(pPg); pPager->dirtyCache = 1; + pPager->dbModified = 1; if( needSyncPgno ){ /* If needSyncPgno is non-zero, then the journal file needs to be @@ -28003,6 +28948,29 @@ SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){ return (int)pPager->exclusiveMode; } +/* +** Get/set the journal-mode for this pager. Parameter eMode must be one +** of PAGER_JOURNALMODE_QUERY, PAGER_JOURNALMODE_DELETE or +** PAGER_JOURNALMODE_PERSIST. If the parameter is not _QUERY, then +** the journal-mode is set to the value specified. +** +** The returned value is either PAGER_JOURNALMODE_DELETE or +** PAGER_JOURNALMODE_PERSIST, indicating the current (possibly updated) +** journal-mode. +*/ +SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_JOURNALMODE_QUERY + || eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_PERSIST + || eMode==PAGER_JOURNALMODE_OFF ); + assert( PAGER_JOURNALMODE_QUERY<0 ); + assert( PAGER_JOURNALMODE_DELETE>=0 && PAGER_JOURNALMODE_PERSIST>=0 ); + if( eMode>=0 ){ + pPager->journalMode = eMode; + } + return (int)pPager->journalMode; +} + #ifdef SQLITE_TEST /* ** Print a listing of all referenced pages and their ref count. @@ -28053,7 +29021,7 @@ SQLITE_PRIVATE void sqlite3PagerRefdump(Pager *pPager){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btreeInt.h,v 1.17 2008/03/04 17:45:01 mlcreech Exp $ +** $Id: btreeInt.h,v 1.21 2008/04/24 19:15:10 shane Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -28437,6 +29405,7 @@ struct BtShared { BtLock *pLock; /* List of locks held on this shared-btree struct */ Btree *pExclusive; /* Btree with an EXCLUSIVE lock on the whole db */ #endif + u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */ }; /* @@ -28474,13 +29443,14 @@ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ - int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ - void *pArg; /* First arg to xCompare() */ + struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ Pgno pgnoRoot; /* The root page of this tree */ MemPage *pPage; /* Page that contains the entry */ int idx; /* Index of the entry in pPage->aCell[] */ CellInfo info; /* A parse of the cell we are pointing at */ u8 wrFlag; /* True if writable */ + u8 atLast; /* Cursor pointing to the last entry */ + u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ void *pKey; /* Saved key that was cursor's last known position */ i64 nKey; /* Size of pKey, or last integer key */ @@ -28532,15 +29502,6 @@ struct BtCursor { # define TRACE(X) #endif -/* -** 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. -*/ -#define getVarint sqlite3GetVarint -#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B)) -#define putVarint sqlite3PutVarint - /* The database page the PENDING_BYTE occupies. This page is never used. ** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They ** should possibly be consolidated (presumably in pager.h). @@ -29002,7 +29963,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.440 2008/03/04 17:45:01 mlcreech Exp $ +** $Id: btree.c,v 1.458 2008/05/09 16:57:51 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -29371,7 +30332,7 @@ SQLITE_PRIVATE int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ } #endif pCur->eState = CURSOR_INVALID; - rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; @@ -29544,7 +30505,7 @@ SQLITE_PRIVATE void sqlite3BtreeParseCellPtr( n = pPage->childPtrSize; assert( n==4-4*pPage->leaf ); if( pPage->hasData ){ - n += getVarint32(&pCell[n], &nPayload); + n += getVarint32(&pCell[n], nPayload); }else{ nPayload = 0; } @@ -29553,7 +30514,7 @@ SQLITE_PRIVATE void sqlite3BtreeParseCellPtr( n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); }else{ u32 x; - n += getVarint32(&pCell[n], &x); + n += getVarint32(&pCell[n], x); pInfo->nKey = x; nPayload += x; } @@ -30046,6 +31007,10 @@ static int getAndInitPage( rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ rc = sqlite3BtreeInitPage(*ppPage, pParent); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + *ppPage = 0; + } } return rc; } @@ -30432,6 +31397,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ pBt->xFreeSchema(pBt->pSchema); } sqlite3_free(pBt->pSchema); + sqlite3_free(pBt->pTmpSpace); sqlite3_free(pBt); } @@ -30536,6 +31502,8 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve) assert( (pageSize & 7)==0 ); assert( !pBt->pPage1 && !pBt->pCursor ); pBt->pageSize = pageSize; + sqlite3_free(pBt->pTmpSpace); + pBt->pTmpSpace = 0; rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); } pBt->usableSize = pBt->pageSize - nReserve; @@ -30627,20 +31595,26 @@ SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){ ** is returned if we run out of memory. */ static int lockBtree(BtShared *pBt){ - int rc, pageSize; + int rc; MemPage *pPage1; + int nPage; assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->pPage1 ) return SQLITE_OK; rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; - /* Do some checking to help insure the file we opened really is ** a valid database file. */ rc = SQLITE_NOTADB; - if( sqlite3PagerPagecount(pBt->pPager)>0 ){ + nPage = sqlite3PagerPagecount(pBt->pPager); + if( nPage<0 ){ + rc = SQLITE_IOERR; + goto page1_init_failed; + }else if( nPage>0 ){ + int pageSize; + int usableSize; u8 *page1 = pPage1->aData; if( memcmp(page1, zMagicHeader, 16)!=0 ){ goto page1_init_failed; @@ -30658,11 +31632,27 @@ static int lockBtree(BtShared *pBt){ goto page1_init_failed; } assert( (pageSize & 7)==0 ); - pBt->pageSize = pageSize; - pBt->usableSize = pageSize - page1[20]; - if( pBt->usableSize<500 ){ + usableSize = pageSize - page1[20]; + if( pageSize!=pBt->pageSize ){ + /* After reading the first page of the database assuming a page size + ** of BtShared.pageSize, we have discovered that the page-size is + ** actually pageSize. Unlock the database, leave pBt->pPage1 at + ** zero and return SQLITE_OK. The caller will call this function + ** again with the correct page-size. + */ + releasePage(pPage1); + pBt->usableSize = usableSize; + pBt->pageSize = pageSize; + sqlite3_free(pBt->pTmpSpace); + pBt->pTmpSpace = 0; + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + return SQLITE_OK; + } + if( usableSize<500 ){ goto page1_init_failed; } + pBt->pageSize = pageSize; + pBt->usableSize = usableSize; pBt->maxEmbedFrac = page1[21]; pBt->minEmbedFrac = page1[22]; pBt->minLeafFrac = page1[23]; @@ -30872,7 +31862,9 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ do { if( pBt->pPage1==0 ){ - rc = lockBtree(pBt); + do{ + rc = lockBtree(pBt); + }while( pBt->pPage1==0 && rc==SQLITE_OK ); } if( rc==SQLITE_OK && wrflag ){ @@ -31287,7 +32279,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ if( rc==SQLITE_DONE ){ assert(nFin==0 || pBt->nTrunc==0 || nFin<=pBt->nTrunc); rc = SQLITE_OK; - if( pBt->nTrunc ){ + if( pBt->nTrunc && nFin ){ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); put4byte(&pBt->pPage1->aData[32], 0); put4byte(&pBt->pPage1->aData[36], 0); @@ -31351,7 +32343,7 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ } } #endif - rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc); + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc, 0); sqlite3BtreeLeave(p); } return rc; @@ -31627,23 +32619,6 @@ SQLITE_PRIVATE int sqlite3BtreeRollbackStmt(Btree *p){ } /* -** Default key comparison function to be used if no comparison function -** is specified on the sqlite3BtreeCursor() call. -*/ -static int dfltCompare( - void *NotUsed, /* User data is not used */ - int n1, const void *p1, /* First key to compare */ - int n2, const void *p2 /* Second key to compare */ -){ - int c; - c = memcmp(p1, p2, n1pBt; assert( sqlite3BtreeHoldsMutex(p) ); - *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; @@ -31708,11 +32674,6 @@ static int btreeCursor( return SQLITE_READONLY; } } - pCur = sqlite3MallocZero( sizeof(*pCur) ); - if( pCur==0 ){ - rc = SQLITE_NOMEM; - goto create_cursor_exception; - } pCur->pgnoRoot = (Pgno)iTable; if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; @@ -31727,8 +32688,7 @@ static int btreeCursor( ** variables, link the cursor into the BtShared list and set *ppCur (the ** output argument to this function). */ - pCur->xCompare = xCmp ? xCmp : dfltCompare; - pCur->pArg = pArg; + pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; pCur->wrFlag = wrFlag; @@ -31738,14 +32698,12 @@ static int btreeCursor( } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; - *ppCur = pCur; return SQLITE_OK; create_cursor_exception: if( pCur ){ releasePage(pCur->pPage); - sqlite3_free(pCur); } unlockBtreeIfUnused(pBt); return rc; @@ -31754,17 +32712,20 @@ SQLITE_PRIVATE int sqlite3BtreeCursor( Btree *p, /* The btree */ int iTable, /* Root page of table to open */ int wrFlag, /* 1 to write. 0 read-only */ - int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */ - void *pArg, /* First arg to xCompare() */ - BtCursor **ppCur /* Write new cursor here */ + struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ + BtCursor *pCur /* Write new cursor here */ ){ int rc; sqlite3BtreeEnter(p); p->pBt->db = p->db; - rc = btreeCursor(p, iTable, wrFlag, xCmp, pArg, ppCur); + rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); sqlite3BtreeLeave(p); return rc; } +SQLITE_PRIVATE int sqlite3BtreeCursorSize(){ + return sizeof(BtCursor); +} + /* @@ -31772,25 +32733,26 @@ SQLITE_PRIVATE int sqlite3BtreeCursor( ** when the last cursor is closed. */ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ - BtShared *pBt = pCur->pBt; Btree *pBtree = pCur->pBtree; - - sqlite3BtreeEnter(pBtree); - pBt->db = pBtree->db; - clearCursorPosition(pCur); - if( pCur->pPrev ){ - pCur->pPrev->pNext = pCur->pNext; - }else{ - pBt->pCursor = pCur->pNext; - } - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur->pPrev; + if( pBtree ){ + BtShared *pBt = pCur->pBt; + sqlite3BtreeEnter(pBtree); + pBt->db = pBtree->db; + clearCursorPosition(pCur); + if( pCur->pPrev ){ + pCur->pPrev->pNext = pCur->pNext; + }else{ + pBt->pCursor = pCur->pNext; + } + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur->pPrev; + } + releasePage(pCur->pPage); + unlockBtreeIfUnused(pBt); + invalidateOverflowCache(pCur); + /* sqlite3_free(pCur); */ + sqlite3BtreeLeave(pBtree); } - releasePage(pCur->pPage); - unlockBtreeIfUnused(pBt); - invalidateOverflowCache(pCur); - sqlite3_free(pCur); - sqlite3BtreeLeave(pBtree); return SQLITE_OK; } @@ -31849,6 +32811,7 @@ SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ static void getCellInfo(BtCursor *pCur){ if( pCur->info.nSize==0 ){ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); + pCur->validNKey = 1; }else{ assertCellInfo(pCur); } @@ -31858,6 +32821,7 @@ SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ #define getCellInfo(pCur) \ if( pCur->info.nSize==0 ){ \ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ + pCur->validNKey = 1; \ }else{ \ assertCellInfo(pCur); \ } @@ -32351,6 +33315,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ pCur->pPage = pNewPage; pCur->idx = 0; pCur->info.nSize = 0; + pCur->validNKey = 0; if( pNewPage->nCell<1 ){ return SQLITE_CORRUPT_BKPT; } @@ -32402,6 +33367,7 @@ SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur){ releasePage(pPage); pCur->pPage = pParent; pCur->info.nSize = 0; + pCur->validNKey = 0; assert( pParent->idxShift==0 ); pCur->idx = idxParent; } @@ -32440,6 +33406,8 @@ static int moveToRoot(BtCursor *pCur){ } pCur->idx = 0; pCur->info.nSize = 0; + pCur->atLast = 0; + pCur->validNKey = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); @@ -32499,6 +33467,7 @@ static int moveToRightmost(BtCursor *pCur){ if( rc==SQLITE_OK ){ pCur->idx = pPage->nCell - 1; pCur->info.nSize = 0; + pCur->validNKey = 0; } return SQLITE_OK; } @@ -32545,18 +33514,20 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( pCur->eState==CURSOR_VALID ); *pRes = 0; rc = moveToRightmost(pCur); + getCellInfo(pCur); + pCur->atLast = rc==SQLITE_OK; } } return rc; } -/* Move the cursor so that it points to an entry near pKey/nKey. -** Return a success code. +/* Move the cursor so that it points to an entry near the key +** specified by pKey/nKey/pUnKey. Return a success code. ** -** For INTKEY tables, only the nKey parameter is used. pKey is -** ignored. For other tables, nKey is the number of bytes of data -** in pKey. The comparison function specified when the cursor was -** created is used to compare keys. +** For INTKEY tables, only the nKey parameter is used. pKey +** and pUnKey must be NULL. For index tables, either pUnKey +** must point to a key that has already been unpacked, or else +** pKey/nKey describes a blob containing the key. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it @@ -32581,14 +33552,31 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ SQLITE_PRIVATE int sqlite3BtreeMoveto( BtCursor *pCur, /* The cursor to be moved */ const void *pKey, /* The key content for indices. Not used by tables */ + UnpackedRecord *pUnKey,/* Unpacked version of pKey */ i64 nKey, /* Size of pKey. Or the key for tables */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Search result flag */ ){ int rc; + char aSpace[200]; assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + + /* If the cursor is already positioned at the point we are trying + ** to move to, then just return without doing any work */ + if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){ + if( pCur->info.nKey==nKey ){ + *pRes = 0; + return SQLITE_OK; + } + if( pCur->atLast && pCur->info.nKeypPage->nCell==0 ); return SQLITE_OK; } + if( pCur->pPage->intKey ){ + /* We are given an SQL table to search. The key is the integer + ** rowid contained in nKey. pKey and pUnKey should both be NULL */ + assert( pUnKey==0 ); + assert( pKey==0 ); + }else if( pUnKey==0 ){ + /* We are to search an SQL index using a key encoded as a blob. + ** The blob is found at pKey and is nKey bytes in length. Unpack + ** this key so that we can use it. */ + assert( pKey!=0 ); + pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey, + aSpace, sizeof(aSpace)); + if( pUnKey==0 ) return SQLITE_NOMEM; + }else{ + /* We are to search an SQL index using a key that is already unpacked + ** and handed to us in pUnKey. */ + assert( pKey==0 ); + } for(;;){ int lwr, upr; Pgno chldPg; @@ -32607,8 +33613,9 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto( int c = -1; /* pRes return if table is empty must be -1 */ lwr = 0; upr = pPage->nCell-1; - if( !pPage->intKey && pKey==0 ){ - return SQLITE_CORRUPT_BKPT; + if( !pPage->intKey && pUnKey==0 ){ + rc = SQLITE_CORRUPT_BKPT; + goto moveto_finish; } if( biasRight ){ pCur->idx = upr; @@ -32619,46 +33626,51 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto( void *pCellKey; i64 nCellKey; pCur->info.nSize = 0; + pCur->validNKey = 1; if( pPage->intKey ){ u8 *pCell; pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; if( pPage->hasData ){ u32 dummy; - pCell += getVarint32(pCell, &dummy); + pCell += getVarint32(pCell, dummy); } - getVarint(pCell, (u64 *)&nCellKey); - if( nCellKeynKey ){ - c = +1; }else{ - c = 0; + assert( nCellKey>nKey ); + c = +1; } }else{ int available; pCellKey = (void *)fetchPayload(pCur, &available, 0); nCellKey = pCur->info.nKey; if( available>=nCellKey ){ - c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); + c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey); }else{ pCellKey = sqlite3_malloc( nCellKey ); - if( pCellKey==0 ) return SQLITE_NOMEM; + if( pCellKey==0 ){ + rc = SQLITE_NOMEM; + goto moveto_finish; + } rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); - c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); + c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey); sqlite3_free(pCellKey); - if( rc ){ - return rc; - } + if( rc ) goto moveto_finish; } } if( c==0 ){ + pCur->info.nKey = nCellKey; if( pPage->leafData && !pPage->leaf ){ lwr = pCur->idx; upr = lwr - 1; break; }else{ if( pRes ) *pRes = 0; - return SQLITE_OK; + rc = SQLITE_OK; + goto moveto_finish; } } if( c<0 ){ @@ -32667,6 +33679,7 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto( upr = pCur->idx-1; } if( lwr>upr ){ + pCur->info.nKey = nCellKey; break; } pCur->idx = (lwr+upr)/2; @@ -32683,16 +33696,22 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto( if( chldPg==0 ){ assert( pCur->idx>=0 && pCur->idxpPage->nCell ); if( pRes ) *pRes = c; - return SQLITE_OK; + rc = SQLITE_OK; + goto moveto_finish; } pCur->idx = lwr; pCur->info.nSize = 0; + pCur->validNKey = 0; rc = moveToChild(pCur, chldPg); - if( rc ){ - return rc; - } + if( rc ) goto moveto_finish; } - /* NOT REACHED */ +moveto_finish: + if( pKey ){ + /* If we created our own unpacked key at the top of this + ** procedure, then destroy that key before returning. */ + sqlite3VdbeDeleteUnpackedRecord(pUnKey); + } + return rc; } @@ -32725,7 +33744,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. */ -static int btreeNext(BtCursor *pCur, int *pRes){ +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage; @@ -32752,6 +33771,7 @@ static int btreeNext(BtCursor *pCur, int *pRes){ pCur->idx++; pCur->info.nSize = 0; + pCur->validNKey = 0; if( pCur->idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); @@ -32784,12 +33804,6 @@ static int btreeNext(BtCursor *pCur, int *pRes){ rc = moveToLeftmost(pCur); return rc; } -SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ - int rc; - assert( cursorHoldsMutex(pCur) ); - rc = btreeNext(pCur, pRes); - return rc; -} /* @@ -32798,7 +33812,7 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. */ -static int btreePrevious(BtCursor *pCur, int *pRes){ +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; @@ -32808,6 +33822,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ if( rc!=SQLITE_OK ){ return rc; } + pCur->atLast = 0; if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; @@ -32841,6 +33856,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ } pCur->idx--; pCur->info.nSize = 0; + pCur->validNKey = 0; if( pPage->leafData && !pPage->leaf ){ rc = sqlite3BtreePrevious(pCur, pRes); }else{ @@ -32850,12 +33866,6 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ *pRes = 0; return rc; } -SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ - int rc; - assert( cursorHoldsMutex(pCur) ); - rc = btreePrevious(pCur, pRes); - return rc; -} /* ** Allocate a new page from the database file. @@ -33043,7 +34053,8 @@ static int allocateBtreePage( *pPgno = iPage; if( *pPgno>sqlite3PagerPagecount(pBt->pPager) ){ /* Free page off the end of the file */ - return SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; } TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" ": %d more free pages\n", @@ -33432,16 +34443,12 @@ static int reparentChildPages(MemPage *pPage){ for(i=0; inCell; i++){ u8 *pCell = findCell(pPage, i); - if( !pPage->leaf ){ - rc = reparentPage(pBt, get4byte(pCell), pPage, i); - if( rc!=SQLITE_OK ) return rc; - } - } - if( !pPage->leaf ){ - rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), - pPage, i); - pPage->idxShift = 0; + rc = reparentPage(pBt, get4byte(pCell), pPage, i); + if( rc!=SQLITE_OK ) return rc; } + rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), + pPage, i); + pPage->idxShift = 0; return rc; } @@ -34558,6 +35565,16 @@ static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ } /* +** Make sure pBt->pTmpSpace points to an allocation of +** MX_CELL_SIZE(pBt) bytes. +*/ +static void allocateTempSpace(BtShared *pBt){ + if( !pBt->pTmpSpace ){ + pBt->pTmpSpace = sqlite3_malloc(MX_CELL_SIZE(pBt)); + } +} + +/* ** Insert a new record into the BTree. The key is given by (pKey,nKey) ** and the data is given by (pData,nData). The cursor is used only to ** define what table the record should be inserted into. The cursor @@ -34603,7 +35620,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( clearCursorPosition(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || - SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc)) ){ return rc; } @@ -34615,7 +35632,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( pCur->pgnoRoot, nKey, nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit ); - newCell = sqlite3_malloc( MX_CELL_SIZE(pBt) ); + allocateTempSpace(pBt); + newCell = pBt->pTmpSpace; if( newCell==0 ) return SQLITE_NOMEM; rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); if( rc ) goto end_insert; @@ -34640,6 +35658,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( assert( pPage->leaf ); pCur->idx++; pCur->info.nSize = 0; + pCur->validNKey = 0; }else{ assert( pPage->leaf ); } @@ -34652,7 +35671,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( moveToRoot(pCur); } end_insert: - sqlite3_free(newCell); return rc; } @@ -34741,7 +35759,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ pNext = findCell(leafCur.pPage, leafCur.idx); szNext = cellSizePtr(leafCur.pPage, pNext); assert( MX_CELL_SIZE(pBt)>=szNext+4 ); - tempCell = sqlite3_malloc( MX_CELL_SIZE(pBt) ); + allocateTempSpace(pBt); + tempCell = pBt->pTmpSpace; if( tempCell==0 ){ rc = SQLITE_NOMEM; } @@ -34757,7 +35776,6 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ rc = balance(leafCur.pPage, 0); } } - sqlite3_free(tempCell); sqlite3BtreeReleaseTempCursor(&leafCur); }else{ TRACE(("DELETE: table=%d delete from leaf %d\n", @@ -35721,62 +36739,205 @@ SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){ ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** -** The size of file pBtFrom may be reduced by this operation. -** If anything goes wrong, the transaction on pBtFrom is rolled back. +** The size of file pTo may be reduced by this operation. +** If anything goes wrong, the transaction on pTo is rolled back. +** +** If successful, CommitPhaseOne() may be called on pTo before returning. +** The caller should finish committing the transaction on pTo by calling +** sqlite3BtreeCommit(). */ static int btreeCopyFile(Btree *pTo, Btree *pFrom){ int rc = SQLITE_OK; - Pgno i, nPage, nToPage, iSkip; + Pgno i; + + Pgno nFromPage; /* Number of pages in pFrom */ + Pgno nToPage; /* Number of pages in pTo */ + Pgno nNewPage; /* Number of pages in pTo after the copy */ + + Pgno iSkip; /* Pending byte page in pTo */ + int nToPageSize; /* Page size of pTo in bytes */ + int nFromPageSize; /* Page size of pFrom in bytes */ BtShared *pBtTo = pTo->pBt; BtShared *pBtFrom = pFrom->pBt; pBtTo->db = pTo->db; pBtFrom->db = pFrom->db; - + + nToPageSize = pBtTo->pageSize; + nFromPageSize = pBtFrom->pageSize; if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ return SQLITE_ERROR; } - if( pBtTo->pCursor ) return SQLITE_BUSY; + if( pBtTo->pCursor ){ + return SQLITE_BUSY; + } + nToPage = sqlite3PagerPagecount(pBtTo->pPager); - nPage = sqlite3PagerPagecount(pBtFrom->pPager); + nFromPage = sqlite3PagerPagecount(pBtFrom->pPager); iSkip = PENDING_BYTE_PAGE(pBtTo); - for(i=1; rc==SQLITE_OK && i<=nPage; i++){ - DbPage *pDbPage; - if( i==iSkip ) continue; - rc = sqlite3PagerGet(pBtFrom->pPager, i, &pDbPage); - if( rc ) break; - rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage)); - sqlite3PagerUnref(pDbPage); - } - /* If the file is shrinking, journal the pages that are being truncated - ** so that they can be rolled back if the commit fails. + /* Variable nNewPage is the number of pages required to store the + ** contents of pFrom using the current page-size of pTo. */ - for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ - DbPage *pDbPage; - if( i==iSkip ) continue; - rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); - if( rc ) break; - rc = sqlite3PagerWrite(pDbPage); - sqlite3PagerDontWrite(pDbPage); - /* Yeah. It seems wierd to call DontWrite() right after Write(). But - ** that is because the names of those procedures do not exactly - ** represent what they do. Write() really means "put this page in the - ** rollback journal and mark it as dirty so that it will be written - ** to the database file later." DontWrite() undoes the second part of - ** that and prevents the page from being written to the database. The - ** page is still on the rollback journal, though. And that is the whole - ** point of this loop: to put pages on the rollback journal. */ - sqlite3PagerUnref(pDbPage); + nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) / + (i64)nToPageSize; + + for(i=1; rc==SQLITE_OK && (i<=nToPage || i<=nNewPage); i++){ + + /* Journal the original page. + ** + ** iSkip is the page number of the locking page (PENDING_BYTE_PAGE) + ** in database *pTo (before the copy). This page is never written + ** into the journal file. Unless i==iSkip or the page was not + ** present in pTo before the copy operation, journal page i from pTo. + */ + if( i!=iSkip && i<=nToPage ){ + DbPage *pDbPage = 0; + rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK && i>nFromPage ){ + /* Yeah. It seems wierd to call DontWrite() right after Write(). But + ** that is because the names of those procedures do not exactly + ** represent what they do. Write() really means "put this page in the + ** rollback journal and mark it as dirty so that it will be written + ** to the database file later." DontWrite() undoes the second part of + ** that and prevents the page from being written to the database. The + ** page is still on the rollback journal, though. And that is the + ** whole point of this block: to put pages on the rollback journal. + */ + sqlite3PagerDontWrite(pDbPage); + } + sqlite3PagerUnref(pDbPage); + } + } + + /* Overwrite the data in page i of the target database */ + if( rc==SQLITE_OK && i!=iSkip && i<=nNewPage ){ + + DbPage *pToPage = 0; + sqlite3_int64 iOff; + + rc = sqlite3PagerGet(pBtTo->pPager, i, &pToPage); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pToPage); + } + + for( + iOff=(i-1)*nToPageSize; + rc==SQLITE_OK && iOffpPager, iFrom, &pFromPage); + if( rc==SQLITE_OK ){ + char *zTo = sqlite3PagerGetData(pToPage); + char *zFrom = sqlite3PagerGetData(pFromPage); + int nCopy; + + if( nFromPageSize>=nToPageSize ){ + zFrom += ((i-1)*nToPageSize - ((iFrom-1)*nFromPageSize)); + nCopy = nToPageSize; + }else{ + zTo += (((iFrom-1)*nFromPageSize) - (i-1)*nToPageSize); + nCopy = nFromPageSize; + } + + memcpy(zTo, zFrom, nCopy); + sqlite3PagerUnref(pFromPage); + } + } + + if( pToPage ) sqlite3PagerUnref(pToPage); + } } - if( !rc && nPagepPager, nPage); + + /* If things have worked so far, the database file may need to be + ** truncated. The complex part is that it may need to be truncated to + ** a size that is not an integer multiple of nToPageSize - the current + ** page size used by the pager associated with B-Tree pTo. + ** + ** For example, say the page-size of pTo is 2048 bytes and the original + ** number of pages is 5 (10 KB file). If pFrom has a page size of 1024 + ** bytes and 9 pages, then the file needs to be truncated to 9KB. + */ + if( rc==SQLITE_OK ){ + if( nFromPageSize!=nToPageSize ){ + sqlite3_file *pFile = sqlite3PagerFile(pBtTo->pPager); + i64 iSize = (i64)nFromPageSize * (i64)nFromPage; + i64 iNow = (i64)((nToPage>nNewPage)?nToPage:nNewPage) * (i64)nToPageSize; + i64 iPending = ((i64)PENDING_BYTE_PAGE(pBtTo)-1) *(i64)nToPageSize; + + assert( iSize<=iNow ); + + /* Commit phase one syncs the journal file associated with pTo + ** containing the original data. It does not sync the database file + ** itself. After doing this it is safe to use OsTruncate() and other + ** file APIs on the database file directly. + */ + pBtTo->db = pTo->db; + rc = sqlite3PagerCommitPhaseOne(pBtTo->pPager, 0, 0, 1); + if( iSizeiPending){ + i64 iOff; + for( + iOff=iPending; + rc==SQLITE_OK && iOff<(iPending+nToPageSize); + iOff += nFromPageSize + ){ + DbPage *pFromPage = 0; + Pgno iFrom = (iOff/nFromPageSize)+1; + + if( iFrom==PENDING_BYTE_PAGE(pBtFrom) || iFrom>nFromPage ){ + continue; + } + + rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage); + if( rc==SQLITE_OK ){ + char *zFrom = sqlite3PagerGetData(pFromPage); + rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff); + sqlite3PagerUnref(pFromPage); + } + } + } + + /* Sync the database file */ + if( rc==SQLITE_OK ){ + rc = sqlite3PagerSync(pBtTo->pPager); + } + }else{ + rc = sqlite3PagerTruncate(pBtTo->pPager, nNewPage); + } + if( rc==SQLITE_OK ){ + pBtTo->pageSizeFixed = 0; + } } if( rc ){ sqlite3BtreeRollback(pTo); } + return rc; } SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ @@ -35864,13 +37025,17 @@ SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){ */ SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ int rc = SQLITE_OK; - u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK); - sqlite3BtreeEnter(p); - rc = queryTableLock(p, iTab, lockType); - if( rc==SQLITE_OK ){ - rc = lockTable(p, iTab, lockType); + if( p->sharable ){ + u8 lockType = READ_LOCK + isWriteLock; + assert( READ_LOCK+1==WRITE_LOCK ); + assert( isWriteLock==0 || isWriteLock==1 ); + sqlite3BtreeEnter(p); + rc = queryTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = lockTable(p, iTab, lockType); + } + sqlite3BtreeLeave(p); } - sqlite3BtreeLeave(p); return rc; } #endif @@ -36135,48 +37300,38 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ ** not set, Mem.n is zeroed. */ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ - int f = pMem->flags; - - assert( (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 - || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Dyn - || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Ephem - || (f & (MEM_Dyn|MEM_Static|MEM_Ephem))==MEM_Static + assert( 1 >= + ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + + (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + + ((pMem->flags&MEM_Ephem) ? 1 : 0) + + ((pMem->flags&MEM_Static) ? 1 : 0) ); - if( ((f&MEM_Dyn)==0 || pMem->xDel || sqlite3MallocSize(pMem->z)0 ){ - if( preserve && (f&MEM_Dyn) && !pMem->xDel ){ - z = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); - pMem->z = 0; - preserve = 0; - }else{ - z = sqlite3DbMallocRaw(pMem->db, (n>32?n:32)); - } - if( !z ){ - return SQLITE_NOMEM; + if( !pMem->zMalloc || sqlite3MallocSize(pMem->zMalloc)32?n:32); + if( preserve && pMem->z==pMem->zMalloc ){ + pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); + if( !pMem->z ){ + pMem->flags = MEM_Null; } + preserve = 0; + }else{ + sqlite3_free(pMem->zMalloc); + pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n); } + } - /* If the value is currently a string or blob and the preserve flag - ** is true, copy the content to the new buffer. - */ - if( pMem->flags&(MEM_Blob|MEM_Str) && preserve ){ - int nCopy = (pMem->n>n?n:pMem->n); - memcpy(z, pMem->z, nCopy); - } - - /* Release the old buffer. */ - sqlite3VdbeMemRelease(pMem); - - pMem->z = z; - pMem->flags |= MEM_Dyn; - pMem->flags &= ~(MEM_Ephem|MEM_Static); - pMem->xDel = 0; + if( preserve && pMem->z && pMem->zMalloc && pMem->z!=pMem->zMalloc ){ + memcpy(pMem->zMalloc, pMem->z, pMem->n); } - return SQLITE_OK; + if( pMem->flags&MEM_Dyn && pMem->xDel ){ + pMem->xDel((void *)(pMem->z)); + } + + pMem->z = pMem->zMalloc; + pMem->flags &= ~(MEM_Ephem|MEM_Static); + pMem->xDel = 0; + return (pMem->z ? SQLITE_OK : SQLITE_NOMEM); } /* @@ -36189,7 +37344,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemDynamicify(Mem *pMem){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); expandBlob(pMem); f = pMem->flags; - if( (f&(MEM_Str|MEM_Blob)) && ((f&MEM_Dyn)==0 || pMem->xDel) ){ + if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){ if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){ return SQLITE_NOMEM; } @@ -36319,13 +37474,13 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); ctx.s.flags = MEM_Null; ctx.s.db = pMem->db; + ctx.s.zMalloc = 0; ctx.pMem = pMem; ctx.pFunc = pFunc; ctx.isError = 0; pFunc->xFinalize(&ctx); - if( pMem->z ){ - sqlite3_free( pMem->z ); - } + assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel ); + sqlite3_free(pMem->zMalloc); *pMem = ctx.s; rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK); } @@ -36333,27 +37488,33 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ } /* +** If the memory cell contains a string value that must be freed by +** invoking an external callback, free it now. Calling this function +** does not free any Mem.zMalloc buffer. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ + assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); + if( p->flags&MEM_Agg ){ + sqlite3VdbeMemFinalize(p, p->u.pDef); + assert( (p->flags & MEM_Agg)==0 ); + sqlite3VdbeMemRelease(p); + }else if( p->flags&MEM_Dyn && p->xDel ){ + p->xDel((void *)p->z); + p->xDel = 0; + } +} + +/* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.type==SQLITE_TEXT). */ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ - assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) ); - if( p->flags & (MEM_Dyn|MEM_Agg) ){ - if( p->xDel ){ - if( p->flags & MEM_Agg ){ - sqlite3VdbeMemFinalize(p, p->u.pDef); - assert( (p->flags & MEM_Agg)==0 ); - sqlite3VdbeMemRelease(p); - }else{ - p->xDel((void *)p->z); - } - }else{ - sqlite3_free(p->z); - } - p->z = 0; - p->xDel = 0; - } + sqlite3VdbeMemReleaseExternal(p); + sqlite3_free(p->zMalloc); + p->z = 0; + p->zMalloc = 0; + p->xDel = 0; } /* @@ -36376,8 +37537,8 @@ static i64 doubleToInt64(double r){ ** So we define our own static constants here using nothing ** larger than a 32-bit integer constant. */ - static const i64 maxInt = (((i64)0x7fffffff)<<32)|0xffffffff; - static const i64 minInt = ((i64)0x80000000)<<32; + static const i64 maxInt = LARGEST_INT64; + static const i64 minInt = SMALLEST_INT64; if( r<(double)minInt ){ return minInt; @@ -36548,7 +37709,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){ ** manifest type REAL. */ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ - if( sqlite3_isnan(val) ){ + if( sqlite3IsNaN(val) ){ sqlite3VdbeMemSetNull(pMem); }else{ sqlite3VdbeMemRelease(pMem); @@ -36563,27 +37724,33 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){ ** too large - whose size exceeds SQLITE_MAX_LENGTH. */ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){ + assert( p->db!=0 ); if( p->flags & (MEM_Str|MEM_Blob) ){ int n = p->n; if( p->flags & MEM_Zero ){ n += p->u.i; } - return n>SQLITE_MAX_LENGTH; + return n>p->db->aLimit[SQLITE_LIMIT_LENGTH]; } return 0; } /* +** Size of struct Mem not including the Mem.zMalloc member. +*/ +#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc)) + +/* ** Make an shallow copy of pFrom into pTo. Prior contents of ** pTo are freed. The pFrom->z field is not duplicated. If ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z ** and flags gets srcType (either MEM_Ephem or MEM_Static). */ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ - sqlite3VdbeMemRelease(pTo); - memcpy(pTo, pFrom, sizeof(*pFrom)); + sqlite3VdbeMemReleaseExternal(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); pTo->xDel = 0; - if( pTo->flags&MEM_Dyn ){ + if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){ pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); assert( srcType==MEM_Ephem || srcType==MEM_Static ); pTo->flags |= srcType; @@ -36596,48 +37763,18 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int sr */ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ int rc = SQLITE_OK; - char *zBuf = 0; - - /* If cell pTo currently has a reusable buffer, save a pointer to it - ** in local variable zBuf. This function attempts to avoid freeing - ** this buffer. - */ - if( pTo->flags&MEM_Dyn ){ - if( pTo->xDel ){ - sqlite3VdbeMemRelease(pTo); - }else{ - zBuf = pTo->z; - } - } - /* Copy the contents of *pFrom to *pTo */ - memcpy(pTo, pFrom, sizeof(*pFrom)); + sqlite3VdbeMemReleaseExternal(pTo); + memcpy(pTo, pFrom, MEMCELLSIZE); + pTo->flags &= ~MEM_Dyn; - if( pTo->flags&(MEM_Str|MEM_Blob) && pTo->flags&MEM_Static ){ - /* pFrom contained a pointer to a static string. In this case, - ** free any dynamically allocated buffer associated with pTo. - */ - sqlite3_free(zBuf); - }else{ - char *zData = pTo->z; - - pTo->z = zBuf; - pTo->flags &= ~(MEM_Static|MEM_Ephem); - pTo->flags |= MEM_Dyn; - pTo->xDel = 0; - - if( pTo->flags&(MEM_Str|MEM_Blob) ){ - if( sqlite3VdbeMemGrow(pTo, pTo->n+2, 0) ){ - pTo->n = 0; - rc = SQLITE_NOMEM; - }else{ - memcpy(pTo->z, zData, pTo->n); - pTo->z[pTo->n] = '\0'; - pTo->z[pTo->n+1] = '\0'; - pTo->flags |= MEM_Term; - } + if( pTo->flags&(MEM_Str|MEM_Blob) ){ + if( 0==(pFrom->flags&MEM_Static) ){ + pTo->flags |= MEM_Ephem; + rc = sqlite3VdbeMemMakeWriteable(pTo); } } + return rc; } @@ -36651,12 +37788,12 @@ SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) ); assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) ); assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db ); - if( pTo->flags & MEM_Dyn ){ - sqlite3VdbeMemRelease(pTo); - } + + sqlite3VdbeMemRelease(pTo); memcpy(pTo, pFrom, sizeof(Mem)); pFrom->flags = MEM_Null; pFrom->xDel = 0; + pFrom->zMalloc = 0; } /* @@ -36710,7 +37847,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( return SQLITE_NOMEM; } memcpy(pMem->z, z, nAlloc); - flags |= MEM_Dyn; }else{ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; @@ -36984,7 +38120,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ expandBlob(pVal); if( pVal->flags&MEM_Str ){ sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); - if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(sqlite3_intptr_t)pVal->z) ){ + if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){ assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 ); if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){ return 0; @@ -36994,7 +38130,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ }else{ assert( (pVal->flags&MEM_Blob)==0 ); sqlite3VdbeMemStringify(pVal, enc); - assert( 0==(1&(sqlite3_intptr_t)pVal->z) ); + assert( 0==(1&(int)pVal->z) ); } assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 || pVal->db->mallocFailed ); @@ -37143,6 +38279,8 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. +** +** $Id: vdbeaux.c,v 1.383 2008/05/13 13:27:34 drh Exp $ */ @@ -37235,14 +38373,10 @@ SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ */ static void resizeOpArray(Vdbe *p, int N){ VdbeOp *pNew; - int oldSize = p->nOpAlloc; pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op)); if( pNew ){ p->nOpAlloc = N; p->aOp = pNew; - if( N>oldSize ){ - memset(&p->aOp[oldSize], 0, (N-oldSize)*sizeof(Op)); - } } } @@ -37277,6 +38411,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ p->nOp++; pOp = &p->aOp[i]; pOp->opcode = op; + pOp->p5 = 0; pOp->p1 = p1; pOp->p2 = p2; pOp->p3 = p3; @@ -37284,8 +38419,13 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ pOp->p4type = P4_NOTUSED; p->expired = 0; #ifdef SQLITE_DEBUG + pOp->zComment = 0; if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); #endif +#ifdef VDBE_PROFILE + pOp->cycles = 0; + pOp->cnt = 0; +#endif return i; } SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){ @@ -37487,6 +38627,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp) pOut->p4.p = 0; pOut->p5 = 0; #ifdef SQLITE_DEBUG + pOut->zComment = 0; if( sqlite3VdbeAddopTrace ){ sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]); } @@ -37658,7 +38799,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int if( n==P4_INT32 ){ /* Note: this cast is safe, because the origin data point was an int ** that was cast to a (const char *). */ - pOp->p4.i = (int)(sqlite3_intptr_t)zP4; + pOp->p4.i = (int)zP4; pOp->p4type = n; }else if( zP4==0 ){ pOp->p4.p = 0; @@ -37864,19 +39005,41 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ /* ** Release an array of N Mem elements */ -static void releaseMemArray(Mem *p, int N){ +static void releaseMemArray(Mem *p, int N, int freebuffers){ if( p && N ){ sqlite3 *db = p->db; int malloc_failed = db->mallocFailed; while( N-->0 ){ assert( N<2 || p[0].db==p[1].db ); - sqlite3VdbeMemRelease(p); - p++->flags = MEM_Null; + if( freebuffers ){ + sqlite3VdbeMemRelease(p); + }else{ + sqlite3VdbeMemReleaseExternal(p); + } + p->flags = MEM_Null; + p++; } db->mallocFailed = malloc_failed; } } +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +SQLITE_PRIVATE int sqlite3VdbeReleaseBuffers(Vdbe *p){ + int ii; + int nFree = 0; + assert( sqlite3_mutex_held(p->db->mutex) ); + for(ii=1; ii<=p->nMem; ii++){ + Mem *pMem = &p->aMem[ii]; + if( pMem->z && pMem->flags&MEM_Dyn ){ + assert( !pMem->xDel ); + nFree += sqlite3MallocSize(pMem->z); + sqlite3VdbeMemRelease(pMem); + } + } + return nFree; +} +#endif + #ifndef SQLITE_OMIT_EXPLAIN /* ** Give a listing of the program in the virtual machine. @@ -37907,7 +39070,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( ** the result, result columns may become dynamic if the user calls ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ - releaseMemArray(pMem, p->nMem); + releaseMemArray(pMem, p->nMem, 1); do{ i = p->pc++; @@ -38085,13 +39248,24 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( */ p->magic = VDBE_MAGIC_RUN; + /* For each cursor required, also allocate a memory cell. Memory + ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by + ** the vdbe program. Instead they are used to allocate space for + ** Cursor/BtCursor structures. The blob of memory associated with + ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) + ** stores the blob of memory associated with cursor 1, etc. + ** + ** See also: allocateCursor(). + */ + nMem += nCursor; + /* ** Allocation space for registers. */ if( p->aMem==0 ){ int nArg; /* Maximum number of args passed to a user function. */ resolveP2Values(p, &nArg); - resizeOpArray(p, p->nOp); + /*resizeOpArray(p, p->nOp);*/ assert( nVar>=0 ); if( isExplain && nMem<10 ){ p->nMem = nMem = 10; @@ -38126,7 +39300,6 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( #ifdef SQLITE_DEBUG for(n=1; nnMem; n++){ assert( p->aMem[n].db==db ); - assert( p->aMem[n].flags==MEM_Null ); } #endif @@ -38153,8 +39326,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( } /* -** Close a VDBE cursor and release all the resources that cursor happens -** to hold. +** Close a VDBE cursor and release all the resources that cursor +** happens to hold. */ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){ if( pCx==0 ){ @@ -38177,9 +39350,12 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){ p->inVtabMethod = 0; } #endif - sqlite3_free(pCx->pData); - sqlite3_free(pCx->aType); - sqlite3_free(pCx); + if( !pCx->ephemPseudoTable ){ + sqlite3_free(pCx->pData); + } + /* memset(pCx, 0, sizeof(Cursor)); */ + /* sqlite3_free(pCx->aType); */ + /* sqlite3_free(pCx); */ } /* @@ -38205,13 +39381,13 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){ ** sorters that were left open. It also deletes the values of ** variables in the aVar[] array. */ -static void Cleanup(Vdbe *p){ +static void Cleanup(Vdbe *p, int freebuffers){ int i; closeAllCursorsExceptActiveVtabs(p); for(i=1; i<=p->nMem; i++){ MemSetTypeFlag(&p->aMem[i], MEM_Null); } - releaseMemArray(&p->aMem[1], p->nMem); + releaseMemArray(&p->aMem[1], p->nMem, freebuffers); sqlite3VdbeFifoClear(&p->sFifo); if( p->contextStack ){ for(i=0; icontextStackTop; i++){ @@ -38237,7 +39413,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ Mem *pColName; int n; - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1); sqlite3_free(p->aColName); n = nResColumn*COLNAME_N; p->nResColumn = nResColumn; @@ -38275,8 +39451,8 @@ SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char * rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT); } if( rc==SQLITE_OK && N==P4_DYNAMIC ){ - pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn; - pColName->xDel = 0; + pColName->flags &= (~MEM_Static); + pColName->zMalloc = pColName->z; } return rc; } @@ -38378,18 +39554,22 @@ static int vdbeCommit(sqlite3 *db){ do { u32 random; sqlite3_free(zMaster); - sqlite3Randomness(sizeof(random), &random); + sqlite3_randomness(sizeof(random), &random); zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff); if( !zMaster ){ return SQLITE_NOMEM; } - }while( sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS) ); - - /* Open the master journal. */ - rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, - SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| - SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0 - ); + rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS); + }while( rc==1 ); + if( rc!=0 ){ + rc = SQLITE_IOERR_NOMEM; + }else{ + /* Open the master journal. */ + rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE| + SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0 + ); + } if( rc!=SQLITE_OK ){ sqlite3_free(zMaster); return rc; @@ -38475,12 +39655,14 @@ static int vdbeCommit(sqlite3 *db){ ** may be lying around. Returning an error code won't help matters. */ disable_simulated_io_errors(); + sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC); for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ sqlite3BtreeCommitPhaseTwo(pBt); } } + sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC); enable_simulated_io_errors(); sqlite3VtabCommit(db); @@ -38737,7 +39919,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ if( p->db->mallocFailed ){ p->rc = SQLITE_NOMEM; } - checkActiveVdbeCnt(db); return SQLITE_OK; } @@ -38762,7 +39943,7 @@ SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){ ** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to ** VDBE_MAGIC_INIT. */ -SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p, int freebuffers){ sqlite3 *db; db = p->db; @@ -38801,7 +39982,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ /* Reclaim all memory used by the VDBE */ - Cleanup(p); + Cleanup(p, freebuffers); /* Save profiling information from this VDBE run. */ @@ -38839,11 +40020,12 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ int rc = SQLITE_OK; if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){ - rc = sqlite3VdbeReset(p); + rc = sqlite3VdbeReset(p, 1); assert( (rc & p->db->errMask)==rc ); }else if( p->magic!=VDBE_MAGIC_INIT ){ return SQLITE_MISUSE; } + releaseMemArray(&p->aMem[1], p->nMem, 1); sqlite3VdbeDelete(p); return rc; } @@ -38873,7 +40055,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ int i; if( p==0 ) return; - Cleanup(p); + Cleanup(p, 1); if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ @@ -38893,12 +40075,12 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ } sqlite3_free(p->aOp); } - releaseMemArray(p->aVar, p->nVar); + releaseMemArray(p->aVar, p->nVar, 1); sqlite3_free(p->aLabel); if( p->aMem ){ sqlite3_free(&p->aMem[1]); } - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1); sqlite3_free(p->aColName); sqlite3_free(p->zSql); p->magic = VDBE_MAGIC_DEAD; @@ -38917,7 +40099,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(Cursor *p){ extern int sqlite3_search_count; #endif assert( p->isTable ); - rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res); + rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res); if( rc ) return rc; *p->pIncrKey = 0; p->lastRowid = keyToInt(p->movetoTarget); @@ -38989,7 +40171,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ } if( flags&MEM_Int ){ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ -# define MAX_6BYTE ((((i64)0x00001000)<<32)-1) +# define MAX_6BYTE ((((i64)0x00008000)<<32)-1) i64 i = pMem->u.i; u64 u; if( file_format>=4 && (i&1)==i ){ @@ -39214,7 +40396,7 @@ SQLITE_PRIVATE int sqlite3VdbeSerialGet( assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); swapMixedEndianFloat(x); memcpy(&pMem->r, &x, sizeof(x)); - pMem->flags = MEM_Real; + pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; } return 8; } @@ -39240,87 +40422,151 @@ SQLITE_PRIVATE int sqlite3VdbeSerialGet( return 0; } + /* -** The header of a record consists of a sequence variable-length integers. -** These integers are almost always small and are encoded as a single byte. -** The following macro takes advantage this fact to provide a fast decode -** of the integers in a record header. It is faster for the common case -** where the integer is a single byte. It is a little slower when the -** integer is two or more bytes. But overall it is faster. -** -** The following expressions are equivalent: -** -** x = sqlite3GetVarint32( A, &B ); +** Given the nKey-byte encoding of a record in pKey[], parse the +** record into a UnpackedRecord structure. Return a pointer to +** that structure. ** -** x = GetVarint( A, B ); +** The calling function might provide szSpace bytes of memory +** space at pSpace. This space can be used to hold the returned +** VDbeParsedRecord structure if it is large enough. If it is +** not big enough, space is obtained from sqlite3_malloc(). ** +** The returned structure should be closed by a call to +** sqlite3VdbeDeleteUnpackedRecord(). +*/ +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack( + KeyInfo *pKeyInfo, /* Information about the record format */ + int nKey, /* Size of the binary record */ + const void *pKey, /* The binary record */ + void *pSpace, /* Space available to hold resulting object */ + int szSpace /* Size of pSpace[] in bytes */ +){ + const unsigned char *aKey = (const unsigned char *)pKey; + UnpackedRecord *p; + int nByte; + int i, idx, d; + u32 szHdr; + Mem *pMem; + + assert( sizeof(Mem)>sizeof(*p) ); + nByte = sizeof(Mem)*(pKeyInfo->nField+2); + if( nByte>szSpace ){ + p = sqlite3DbMallocRaw(pKeyInfo->db, nByte); + if( p==0 ) return 0; + p->needFree = 1; + }else{ + p = pSpace; + p->needFree = 0; + } + p->pKeyInfo = pKeyInfo; + p->nField = pKeyInfo->nField + 1; + p->needDestroy = 1; + p->aMem = pMem = &((Mem*)p)[1]; + idx = getVarint32(aKey, szHdr); + d = szHdr; + i = 0; + while( idxnField ){ + u32 serial_type; + + idx += getVarint32( aKey+idx, serial_type); + if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break; + pMem->enc = pKeyInfo->enc; + pMem->db = pKeyInfo->db; + pMem->flags = 0; + pMem->zMalloc = 0; + d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + pMem++; + i++; + } + p->nField = i; + return (void*)p; +} + +/* +** This routine destroys a UnpackedRecord object */ -#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B)) +SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ + if( p ){ + if( p->needDestroy ){ + int i; + Mem *pMem; + for(i=0, pMem=p->aMem; inField; i++, pMem++){ + if( pMem->zMalloc ){ + sqlite3VdbeMemRelease(pMem); + } + } + } + if( p->needFree ){ + sqlite3_free(p); + } + } +} /* -** This function compares the two table rows or index records specified by -** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero +** This function compares the two table rows or index records +** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero ** or positive integer if {nKey1, pKey1} is less than, equal to or -** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings -** composed by the OP_MakeRecord opcode of the VDBE. +** greater than pPKey2. The {nKey1, pKey1} key must be a blob +** created by th OP_MakeRecord opcode of the VDBE. The pPKey2 +** key must be a parsed key such as obtained from +** sqlite3VdbeParseRecord. ** ** Key1 and Key2 do not have to contain the same number of fields. ** But if the lengths differ, Key2 must be the shorter of the two. +** +** Historical note: In earlier versions of this routine both Key1 +** and Key2 were blobs obtained from OP_MakeRecord. But we found +** that in typical use the same Key2 would be submitted multiple times +** in a row. So an optimization was added to parse the Key2 key +** separately and submit the parsed version. In this way, we avoid +** parsing the same Key2 multiple times in a row. */ SQLITE_PRIVATE int sqlite3VdbeRecordCompare( - void *userData, int nKey1, const void *pKey1, - int nKey2, const void *pKey2 + UnpackedRecord *pPKey2 ){ - KeyInfo *pKeyInfo = (KeyInfo*)userData; - u32 d1, d2; /* Offset into aKey[] of next data element */ - u32 idx1, idx2; /* Offset into aKey[] of next header element */ - u32 szHdr1, szHdr2; /* Number of bytes in header */ + u32 d1; /* Offset into aKey[] of next data element */ + u32 idx1; /* Offset into aKey[] of next header element */ + u32 szHdr1; /* Number of bytes in header */ int i = 0; int nField; int rc = 0; const unsigned char *aKey1 = (const unsigned char *)pKey1; - const unsigned char *aKey2 = (const unsigned char *)pKey2; - + KeyInfo *pKeyInfo; Mem mem1; - Mem mem2; + + pKeyInfo = pPKey2->pKeyInfo; mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; mem1.flags = 0; - mem2.enc = pKeyInfo->enc; - mem2.db = pKeyInfo->db; - mem2.flags = 0; + mem1.zMalloc = 0; - idx1 = GetVarint(aKey1, szHdr1); + idx1 = getVarint32(aKey1, szHdr1); d1 = szHdr1; - idx2 = GetVarint(aKey2, szHdr2); - d2 = szHdr2; nField = pKeyInfo->nField; - while( idx1nField ){ u32 serial_type1; - u32 serial_type2; /* Read the serial types for the next element in each key. */ - idx1 += GetVarint( aKey1+idx1, serial_type1 ); + idx1 += getVarint32( aKey1+idx1, serial_type1 ); if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; - idx2 += GetVarint( aKey2+idx2, serial_type2 ); - if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break; /* Extract the values to be compared. */ d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); - d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2); /* Do the comparison */ - rc = sqlite3MemCompare(&mem1, &mem2, iaColl[i] : 0); - if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1); - if( mem2.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem2); + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], + iaColl[i] : 0); if( rc!=0 ){ break; } i++; } + if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1); /* One of the keys ran out of fields, but all the fields up to that point ** were equal. If the incrKey flag is true, then the second key is @@ -39332,8 +40578,6 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare( }else if( !pKeyInfo->prefixIsEqual ){ if( d1aSortOrder && inField @@ -39354,8 +40598,8 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8 *aKey){ u32 szHdr; /* Size of the header */ u32 typeRowid; /* Serial type of the rowid */ - sqlite3GetVarint32(aKey, &szHdr); - sqlite3GetVarint32(&aKey[szHdr-1], &typeRowid); + (void)getVarint32(aKey, szHdr); + (void)getVarint32(&aKey[szHdr-1], typeRowid); return sqlite3VdbeSerialTypeLen(typeRowid); } @@ -39379,12 +40623,13 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ } m.flags = 0; m.db = 0; + m.zMalloc = 0; rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m); if( rc ){ return rc; } - sqlite3GetVarint32((u8*)m.z, &szHdr); - sqlite3GetVarint32((u8*)&m.z[szHdr-1], &typeRowid); + (void)getVarint32((u8*)m.z, szHdr); + (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid); lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); *rowid = v.u.i; @@ -39404,6 +40649,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ */ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( Cursor *pC, /* The cursor to compare against */ + UnpackedRecord *pUnpacked, int nKey, const u8 *pKey, /* The key to compare */ int *res /* Write the comparison result here */ ){ @@ -39412,6 +40658,8 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( BtCursor *pCur = pC->pCursor; int lenRowid; Mem m; + UnpackedRecord *pRec; + char zSpace[200]; sqlite3BtreeKeySize(pCur, &nCellKey); if( nCellKey<=0 ){ @@ -39420,12 +40668,25 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( } m.db = 0; m.flags = 0; + m.zMalloc = 0; rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m); if( rc ){ return rc; } lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z); - *res = sqlite3VdbeRecordCompare(pC->pKeyInfo, m.n-lenRowid, m.z, nKey, pKey); + if( !pUnpacked ){ + pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey, + zSpace, sizeof(zSpace)); + }else{ + pRec = pUnpacked; + } + if( pRec==0 ){ + return SQLITE_NOMEM; + } + *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec); + if( !pUnpacked ){ + sqlite3VdbeDeleteUnpackedRecord(pRec); + } sqlite3VdbeMemRelease(&m); return SQLITE_OK; } @@ -39490,6 +40751,162 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){ ** VDBE. */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* +** The following structure contains pointers to the end points of a +** doubly-linked list of all compiled SQL statements that may be holding +** buffers eligible for release when the sqlite3_release_memory() interface is +** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2 +** mutex. +** +** Statements are added to the end of this list when sqlite3_reset() is +** called. They are removed either when sqlite3_step() or sqlite3_finalize() +** is called. When statements are added to this list, the associated +** register array (p->aMem[1..p->nMem]) may contain dynamic buffers that +** can be freed using sqlite3VdbeReleaseMemory(). +** +** When statements are added or removed from this list, the mutex +** associated with the Vdbe being added or removed (Vdbe.db->mutex) is +** already held. The LRU2 mutex is then obtained, blocking if necessary, +** the linked-list pointers manipulated and the LRU2 mutex relinquished. +*/ +struct StatementLruList { + Vdbe *pFirst; + Vdbe *pLast; +}; +static struct StatementLruList sqlite3LruStatements; + +/* +** Check that the list looks to be internally consistent. This is used +** as part of an assert() statement as follows: +** +** assert( stmtLruCheck() ); +*/ +#ifndef NDEBUG +static int stmtLruCheck(){ + Vdbe *p; + for(p=sqlite3LruStatements.pFirst; p; p=p->pLruNext){ + assert(p->pLruNext || p==sqlite3LruStatements.pLast); + assert(!p->pLruNext || p->pLruNext->pLruPrev==p); + assert(p->pLruPrev || p==sqlite3LruStatements.pFirst); + assert(!p->pLruPrev || p->pLruPrev->pLruNext==p); + } + return 1; +} +#endif + +/* +** Add vdbe p to the end of the statement lru list. It is assumed that +** p is not already part of the list when this is called. The lru list +** is protected by the SQLITE_MUTEX_STATIC_LRU mutex. +*/ +static void stmtLruAdd(Vdbe *p){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + + if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){ + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + return; + } + + assert( stmtLruCheck() ); + + if( !sqlite3LruStatements.pFirst ){ + assert( !sqlite3LruStatements.pLast ); + sqlite3LruStatements.pFirst = p; + sqlite3LruStatements.pLast = p; + }else{ + assert( !sqlite3LruStatements.pLast->pLruNext ); + p->pLruPrev = sqlite3LruStatements.pLast; + sqlite3LruStatements.pLast->pLruNext = p; + sqlite3LruStatements.pLast = p; + } + + assert( stmtLruCheck() ); + + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); +} + +/* +** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove +** statement p from the least-recently-used statement list. If the +** statement is not currently part of the list, this call is a no-op. +*/ +static void stmtLruRemoveNomutex(Vdbe *p){ + if( p->pLruPrev || p->pLruNext || p==sqlite3LruStatements.pFirst ){ + assert( stmtLruCheck() ); + if( p->pLruNext ){ + p->pLruNext->pLruPrev = p->pLruPrev; + }else{ + sqlite3LruStatements.pLast = p->pLruPrev; + } + if( p->pLruPrev ){ + p->pLruPrev->pLruNext = p->pLruNext; + }else{ + sqlite3LruStatements.pFirst = p->pLruNext; + } + p->pLruNext = 0; + p->pLruPrev = 0; + assert( stmtLruCheck() ); + } +} + +/* +** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove +** statement p from the least-recently-used statement list. If the +** statement is not currently part of the list, this call is a no-op. +*/ +static void stmtLruRemove(Vdbe *p){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + stmtLruRemoveNomutex(p); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); +} + +/* +** Try to release n bytes of memory by freeing buffers associated +** with the memory registers of currently unused vdbes. +*/ +SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int n){ + Vdbe *p; + Vdbe *pNext; + int nFree = 0; + + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + for(p=sqlite3LruStatements.pFirst; p && nFreepLruNext; + + /* For each statement handle in the lru list, attempt to obtain the + ** associated database mutex. If it cannot be obtained, continue + ** to the next statement handle. It is not possible to block on + ** the database mutex - that could cause deadlock. + */ + if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){ + nFree += sqlite3VdbeReleaseBuffers(p); + stmtLruRemoveNomutex(p); + sqlite3_mutex_leave(p->db->mutex); + } + } + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU2)); + + return nFree; +} + +/* +** Call sqlite3Reprepare() on the statement. Remove it from the +** lru list before doing so, as Reprepare() will free all the +** memory register buffers anyway. +*/ +int vdbeReprepare(Vdbe *p){ + stmtLruRemove(p); + return sqlite3Reprepare(p); +} + +#else /* !SQLITE_ENABLE_MEMORY_MANAGEMENT */ + #define stmtLruRemove(x) + #define stmtLruAdd(x) + #define vdbeReprepare(x) sqlite3Reprepare(x) +#endif + + /* ** Return TRUE (non-zero) of the statement supplied as an argument needs ** to be recompiled. A statement needs to be recompiled whenever the @@ -39522,6 +40939,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ sqlite3_mutex *mutex = v->db->mutex; #endif sqlite3_mutex_enter(mutex); + stmtLruRemove(v); rc = sqlite3VdbeFinalize(v); sqlite3_mutex_leave(mutex); } @@ -39543,7 +40961,8 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); - rc = sqlite3VdbeReset(v); + rc = sqlite3VdbeReset(v, 1); + stmtLruAdd(v); sqlite3VdbeMakeReady(v, -1, 0, 0, 0); assert( (rc & (v->db->errMask))==rc ); sqlite3_mutex_leave(v->db->mutex); @@ -39557,12 +40976,14 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; + Vdbe *p = (Vdbe*)pStmt; #ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); - for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ - rc = sqlite3_bind_null(pStmt, i); + for(i=0; inVar; i++){ + sqlite3VdbeMemRelease(&p->aVar[i]); + p->aVar[i].flags = MEM_Null; } sqlite3_mutex_leave(mutex); return rc; @@ -39712,7 +41133,9 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ /* Force an SQLITE_TOOBIG error. */ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); - sqlite3VdbeMemSetZeroBlob(&pCtx->s, SQLITE_MAX_LENGTH+1); + pCtx->isError = SQLITE_TOOBIG; + sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, + SQLITE_UTF8, SQLITE_STATIC); } /* An SQLITE_NOMEM error. */ @@ -39778,6 +41201,7 @@ static int sqlite3Step(Vdbe *p){ db->activeVdbeCnt++; p->pc = 0; + stmtLruRemove(p); } #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ @@ -39849,7 +41273,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < 5 - && sqlite3Reprepare(v) ){ + && vdbeReprepare(v) ){ sqlite3_reset(pStmt); v->expired = 0; } @@ -39888,6 +41312,15 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){ } /* +** Extract the user data from a sqlite3_context structure and return a +** pointer to it. +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ + assert( p && p->pFunc ); + return p->s.db; +} + +/* ** The following is the implementation of an SQL function that always ** fails with an error message stating that the function is used in the ** wrong context. The sqlite3_overload_function() API might construct @@ -39920,13 +41353,16 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ pMem = p->pMem; if( (pMem->flags & MEM_Agg)==0 ){ if( nByte==0 ){ - assert( pMem->flags==MEM_Null ); + sqlite3VdbeMemReleaseExternal(pMem); + pMem->flags = MEM_Null; pMem->z = 0; }else{ + sqlite3VdbeMemGrow(pMem, nByte, 0); pMem->flags = MEM_Agg; - pMem->xDel = sqlite3_free; pMem->u.pDef = p->pFunc; - pMem->z = sqlite3DbMallocZero(p->s.db, nByte); + if( pMem->z ){ + memset(pMem->z, 0, nByte); + } } } return (void*)pMem->z; @@ -40041,7 +41477,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ vals = sqlite3_data_count(pStmt); pOut = &pVm->pResultSet[i]; }else{ - static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL }; + static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 }; if( pVm->db ){ sqlite3_mutex_enter(pVm->db->mutex); sqlite3Error(pVm->db, SQLITE_RANGE, 0); @@ -40216,6 +41652,16 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ #endif /* +** Constraint: If you have ENABLE_COLUMN_METADATA then you must +** not define OMIT_DECLTYPE. +*/ +#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA) +# error "Must not define both SQLITE_OMIT_DECLTYPE \ + and SQLITE_ENABLE_COLUMN_METADATA" +#endif + +#ifndef SQLITE_OMIT_DECLTYPE +/* ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt. */ @@ -40229,6 +41675,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); } #endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_OMIT_DECLTYPE */ #ifdef SQLITE_ENABLE_COLUMN_METADATA /* @@ -40587,7 +42034,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.711 2008/03/17 17:18:38 drh Exp $ +** $Id: vdbe.c,v 1.740 2008/05/13 13:27:34 drh Exp $ */ /* @@ -40644,7 +42091,7 @@ static void updateMaxBlobsize(Mem *p){ ** Test a register to see if it exceeds the current maximum blob size. ** If it does, record the new maximum blob size. */ -#ifdef SQLITE_TEST +#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST) # define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) #else # define UPDATE_MAX_BLOBSIZE(P) @@ -40665,23 +42112,6 @@ static void updateMaxBlobsize(Mem *p){ { goto no_mem; } /* -** The header of a record consists of a sequence variable-length integers. -** These integers are almost always small and are encoded as a single byte. -** The following macro takes advantage this fact to provide a fast decode -** of the integers in a record header. It is faster for the common case -** where the integer is a single byte. It is a little slower when the -** integer is two or more bytes. But overall it is faster. -** -** The following expressions are equivalent: -** -** x = sqlite3GetVarint32( A, &B ); -** -** x = GetVarint( A, B ); -** -*/ -#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B)) - -/* ** An ephemeral string value (signified by the MEM_Ephem flag) contains ** a pointer to a dynamically allocated string where some other entity ** is responsible for deallocating that string. Because the register @@ -40749,15 +42179,65 @@ SQLITE_PRIVATE int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){ ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ -static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){ - Cursor *pCx; +static Cursor *allocateCursor( + Vdbe *p, + int iCur, + Op *pOp, + int iDb, + int isBtreeCursor +){ + /* Find the memory cell that will be used to store the blob of memory + ** required for this Cursor structure. It is convenient to use a + ** vdbe memory cell to manage the memory allocation required for a + ** Cursor structure for the following reasons: + ** + ** * Sometimes cursor numbers are used for a couple of different + ** purposes in a vdbe program. The different uses might require + ** different sized allocations. Memory cells provide growable + ** allocations. + ** + ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can + ** be freed lazily via the sqlite3_release_memory() API. This + ** minimizes the number of malloc calls made by the system. + ** + ** Memory cells for cursors are allocated at the top of the address + ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for + ** cursor 1 is managed by memory cell (p->nMem-1), etc. + */ + Mem *pMem = &p->aMem[p->nMem-iCur]; + + int nByte; + Cursor *pCx = 0; + /* If the opcode of pOp is OP_SetNumColumns, then pOp->p2 contains + ** the number of fields in the records contained in the table or + ** index being opened. Use this to reserve space for the + ** Cursor.aType[] array. + */ + int nField = 0; + if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){ + nField = pOp->p2; + } + nByte = + sizeof(Cursor) + + (isBtreeCursor?sqlite3BtreeCursorSize():0) + + 2*nField*sizeof(u32); + assert( iCurnCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); + p->apCsr[iCur] = 0; } - p->apCsr[iCur] = pCx = sqlite3MallocZero( sizeof(Cursor) ); - if( pCx ){ + if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){ + p->apCsr[iCur] = pCx = (Cursor *)pMem->z; + memset(pMem->z, 0, nByte); pCx->iDb = iDb; + pCx->nField = nField; + if( nField ){ + pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)]; + } + if( isBtreeCursor ){ + pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)]; + } } return pCx; } @@ -40980,11 +42460,10 @@ static void registerTrace(FILE *out, int iReg, Mem *p){ ** profiling. */ __inline__ unsigned long long int hwtime(void){ - unsigned long long int x; - __asm__("rdtsc\n\t" - "mov %%edx, %%ecx\n\t" - :"=A" (x)); - return x; + unsigned int lo, hi; + /* We cannot use "=A", since this would use %rax on x86_64 */ + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return (unsigned long long int)hi << 32 | lo; } #endif @@ -41068,8 +42547,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec( CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); #ifdef SQLITE_DEBUG + sqlite3FaultBeginBenign(-1); if( p->pc==0 && ((p->db->flags & SQLITE_VdbeListing)!=0 - || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS)) + || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS)==1 ) ){ int i; printf("VDBE Program Listing:\n"); @@ -41078,9 +42558,10 @@ SQLITE_PRIVATE int sqlite3VdbeExec( sqlite3VdbePrintOp(stdout, i, &p->aOp[i]); } } - if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS) ){ + if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS)==1 ){ p->trace = stdout; } + sqlite3FaultEndBenign(-1); #endif for(pc=p->pc; rc==SQLITE_OK; pc++){ assert( pc>=0 && pcnOp ); @@ -41101,9 +42582,12 @@ SQLITE_PRIVATE int sqlite3VdbeExec( } sqlite3VdbePrintOp(p->trace, pc, pOp); } - if( p->trace==0 && pc==0 - && sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS) ){ - sqlite3VdbePrintSql(p); + if( p->trace==0 && pc==0 ){ + sqlite3FaultBeginBenign(-1); + if( sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS)==1 ){ + sqlite3VdbePrintSql(p); + } + sqlite3FaultEndBenign(-1); } #endif @@ -41153,7 +42637,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( pOp->p2>0 ); assert( pOp->p2<=p->nMem ); pOut = &p->aMem[pOp->p2]; - sqlite3VdbeMemRelease(pOut); + sqlite3VdbeMemReleaseExternal(pOut); pOut->flags = MEM_Null; }else @@ -41346,6 +42830,7 @@ case OP_Int64: { /* out2-prerelease */ */ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ pOut->flags = MEM_Real; + assert( !sqlite3IsNaN(*pOp->p4.pReal) ); pOut->r = *pOp->p4.pReal; break; } @@ -41365,22 +42850,23 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pOut) ) goto no_mem; - pOut->flags &= ~(MEM_Dyn); + pOut->zMalloc = 0; pOut->flags |= MEM_Static; + pOut->flags &= ~MEM_Dyn; if( pOp->p4type==P4_DYNAMIC ){ sqlite3_free(pOp->p4.z); } pOp->p4type = P4_DYNAMIC; pOp->p4.z = pOut->z; pOp->p1 = pOut->n; - if( pOp->p1>SQLITE_MAX_LENGTH ){ + if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } UPDATE_MAX_BLOBSIZE(pOut); break; } #endif - if( pOp->p1>SQLITE_MAX_LENGTH ){ + if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } /* Fall through to the next case, OP_String */ @@ -41457,6 +42943,24 @@ case OP_Variable: { /* out2-prerelease */ ** is left holding a NULL. It is an error for P1 and P2 to be the ** same register. */ +case OP_Move: { + char *zMalloc; + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + assert( pOut!=pIn1 ); + zMalloc = pOut->zMalloc; + pOut->zMalloc = 0; + sqlite3VdbeMemMove(pOut, pIn1); + pIn1->zMalloc = zMalloc; + REGISTER_TRACE(pOp->p2, pOut); + break; +} + /* Opcode: Copy P1 P2 * * * ** ** Make a copy of register P1 into register P2. @@ -41464,6 +42968,21 @@ case OP_Variable: { /* out2-prerelease */ ** This instruction makes a deep copy of the value. A duplicate ** is made of any string or blob constant. See also OP_SCopy. */ +case OP_Copy: { + assert( pOp->p1>0 ); + assert( pOp->p1<=p->nMem ); + pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); + assert( pOp->p2>0 ); + assert( pOp->p2<=p->nMem ); + pOut = &p->aMem[pOp->p2]; + assert( pOut!=pIn1 ); + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); + Deephemeralize(pOut); + REGISTER_TRACE(pOp->p2, pOut); + break; +} + /* Opcode: SCopy P1 P2 * * * ** ** Make a shallow copy of register P1 into register P2. @@ -41476,8 +42995,6 @@ case OP_Variable: { /* out2-prerelease */ ** during the lifetime of the copy. Use OP_Copy to make a complete ** copy. */ -case OP_Move: -case OP_Copy: case OP_SCopy: { assert( pOp->p1>0 ); assert( pOp->p1<=p->nMem ); @@ -41487,14 +43004,7 @@ case OP_SCopy: { assert( pOp->p2<=p->nMem ); pOut = &p->aMem[pOp->p2]; assert( pOut!=pIn1 ); - if( pOp->opcode==OP_Move ){ - sqlite3VdbeMemMove(pOut, pIn1); - }else{ - sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); - if( pOp->opcode==OP_Copy ){ - Deephemeralize(pOut); - } - } + sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); REGISTER_TRACE(pOp->p2, pOut); break; } @@ -41561,7 +43071,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ ExpandBlob(pIn2); Stringify(pIn2, encoding); nByte = pIn1->n + pIn2->n; - if( nByte>SQLITE_MAX_LENGTH ){ + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } MemSetTypeFlag(pOut, MEM_Str); @@ -41633,13 +43143,13 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ case OP_Divide: { if( a==0 ) goto arithmetic_result_is_null; /* Dividing the largest possible negative 64-bit integer (1<<63) by - ** -1 returns an integer to large to store in a 64-bit data-type. On + ** -1 returns an integer too large to store in a 64-bit data-type. On ** some architectures, the value overflows to (1<<63). On others, ** a SIGFPE is issued. The following statement normalizes this ** behaviour so that all architectures behave as if integer ** overflow occured. */ - if( a==-1 && b==(((i64)1)<<63) ) a = 1; + if( a==-1 && b==SMALLEST_INT64 ) a = 1; b /= a; break; } @@ -41674,7 +43184,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ break; } } - if( sqlite3_isnan(b) ){ + if( sqlite3IsNaN(b) ){ goto arithmetic_result_is_null; } pOut->r = b; @@ -41753,7 +43263,9 @@ case OP_Function: { assert( pOp->p3>0 && pOp->p3<=p->nMem ); pOut = &p->aMem[pOp->p3]; ctx.s.flags = MEM_Null; - ctx.s.db = 0; + ctx.s.db = db; + ctx.s.xDel = 0; + ctx.s.zMalloc = 0; /* The output cell may already have a buffer allocated. Move ** the pointer to ctx.s so in case the user-function can use @@ -41771,7 +43283,10 @@ case OP_Function: { } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; (*ctx.pFunc->xFunc)(&ctx, n, apVal); - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; + if( sqlite3SafetyOn(db) ){ + sqlite3VdbeMemRelease(&ctx.s); + goto abort_due_to_misuse; + } if( db->mallocFailed ){ /* Even though a malloc() has failed, the implementation of the ** user function may have called an sqlite3_result_XXX() function @@ -42314,22 +43829,23 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ break; } -/* Opcode: SetNumColumns P1 P2 * * * +/* Opcode: SetNumColumns * P2 * * * +** +** This opcode sets the number of columns for the cursor opened by the +** following instruction to P2. ** -** Before the OP_Column opcode can be executed on a cursor, this -** opcode must be called to set the number of fields in the table. +** An OP_SetNumColumns is only useful if it occurs immediately before +** one of the following opcodes: ** -** This opcode sets the number of columns for cursor P1 to P2. +** OpenRead +** OpenWrite +** OpenPseudo ** -** If OP_KeyAsData is to be applied to cursor P1, it must be executed -** before this op-code. +** If the OP_Column opcode is to be executed on a cursor, then +** this opcode must be present immediately before the opcode that +** opens the cursor. */ case OP_SetNumColumns: { - Cursor *pC; - assert( (pOp->p1)nCursor ); - assert( p->apCsr[pOp->p1]!=0 ); - pC = p->apCsr[pOp->p1]; - pC->nField = pOp->p2; break; } @@ -42368,6 +43884,7 @@ case OP_Column: { sMem.flags = 0; sMem.db = 0; + sMem.zMalloc = 0; assert( p1nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &p->aMem[pOp->p3]; @@ -42425,7 +43942,7 @@ case OP_Column: { assert( pDest->flags&MEM_Null ); goto op_column_out; } - if( payloadSize>SQLITE_MAX_LENGTH ){ + if( payloadSize>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } @@ -42434,8 +43951,8 @@ case OP_Column: { /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ + aType = pC->aType; if( pC->cacheStatus==p->cacheCtr ){ - aType = pC->aType; aOffset = pC->aOffset; }else{ u8 *zIdx; /* Index into header */ @@ -42444,13 +43961,7 @@ case OP_Column: { int szHdrSz; /* Size of the header size field at start of record */ int avail; /* Number of bytes of available data */ - aType = pC->aType; - if( aType==0 ){ - pC->aType = aType = sqlite3DbMallocRaw(db, 2*nField*sizeof(aType) ); - } - if( aType==0 ){ - goto no_mem; - } + assert(aType); pC->aOffset = aOffset = &aType[nField]; pC->payloadSize = payloadSize; pC->cacheStatus = p->cacheCtr; @@ -42479,7 +43990,7 @@ case OP_Column: { /* The following assert is true in all cases accept when ** the database file has been corrupted externally. ** assert( zRec!=0 || avail>=payloadSize || avail>=9 ); */ - szHdrSz = GetVarint((u8*)zData, offset); + szHdrSz = getVarint32((u8*)zData, offset); /* The KeyFetch() or DataFetch() above are fast and will get the entire ** record header in most cases. But they will fail to get the complete @@ -42507,7 +44018,7 @@ case OP_Column: { for(i=0; izEndHdr || offset>payloadSize ){ + if( zIdx>zEndHdr || offset>payloadSize || (zIdx==zEndHdr && offset!=payloadSize) ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; } @@ -42544,8 +44057,11 @@ case OP_Column: { if( pDest->flags&MEM_Dyn ){ sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], &sMem); sMem.db = db; - sqlite3VdbeMemCopy(pDest, &sMem); + rc = sqlite3VdbeMemCopy(pDest, &sMem); assert( !(sMem.flags&MEM_Dyn) ); + if( rc!=SQLITE_OK ){ + goto op_column_out; + } }else{ sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest); } @@ -42573,13 +44089,14 @@ case OP_Column: { ** dynamically allocated space over to the pDest structure. ** This prevents a memory copy. */ - if( (sMem.flags & MEM_Dyn)!=0 ){ - assert( !sMem.xDel ); + if( sMem.zMalloc ){ + assert( sMem.z==sMem.zMalloc ); assert( !(pDest->flags & MEM_Dyn) ); assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z ); pDest->flags &= ~(MEM_Ephem|MEM_Static); - pDest->flags |= MEM_Dyn|MEM_Term; + pDest->flags |= MEM_Term; pDest->z = sMem.z; + pDest->zMalloc = sMem.zMalloc; } rc = sqlite3VdbeMemMakeWriteable(pDest); @@ -42590,17 +44107,37 @@ op_column_out: break; } +/* Opcode: Affinity P1 P2 * P4 * +** +** Apply affinities to a range of P2 registers starting with P1. +** +** P4 is a string that is P2 characters long. The nth character of the +** string indicates the column affinity that should be used for the nth +** memory cell in the range. +*/ +case OP_Affinity: { + char *zAffinity = pOp->p4.z; + Mem *pData0 = &p->aMem[pOp->p1]; + Mem *pLast = &pData0[pOp->p2-1]; + Mem *pRec; + + for(pRec=pData0; pRec<=pLast; pRec++){ + ExpandBlob(pRec); + applyAffinity(pRec, zAffinity[pRec-pData0], encoding); + } + break; +} + /* Opcode: MakeRecord P1 P2 P3 P4 * ** ** Convert P2 registers beginning with P1 into a single entry ** suitable for use as a data record in a database table or as a key ** in an index. The details of the format are irrelavant as long as -** the OP_Column opcode can decode the record later and as long as the -** sqlite3VdbeRecordCompare function will correctly compare two encoded -** records. Refer to source code comments for the details of the record +** the OP_Column opcode can decode the record later. +** Refer to source code comments for the details of the record ** format. ** -** P4 may be a string that is P1 characters long. The nth character of the +** P4 may be a string that is P2 characters long. The nth character of the ** string indicates the column affinity that should be used for the nth ** field of the index key. ** @@ -42678,7 +44215,7 @@ case OP_MakeRecord: { nHdr++; } nByte = nHdr+nData-nZero; - if( nByte>SQLITE_MAX_LENGTH ){ + if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } @@ -42695,10 +44232,10 @@ case OP_MakeRecord: { zNewRecord = (u8 *)pOut->z; /* Write the record */ - i = sqlite3PutVarint(zNewRecord, nHdr); + i = putVarint32(zNewRecord, nHdr); for(pRec=pData0; pRec<=pLast; pRec++){ serial_type = sqlite3VdbeSerialType(pRec, file_format); - i += sqlite3PutVarint(&zNewRecord[i], serial_type); /* serial type */ + i += putVarint32(&zNewRecord[i], serial_type); /* serial type */ } for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */ i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format); @@ -42722,11 +44259,21 @@ case OP_MakeRecord: { /* Opcode: Statement P1 * * * * ** ** Begin an individual statement transaction which is part of a larger -** BEGIN..COMMIT transaction. This is needed so that the statement +** transaction. This is needed so that the statement ** can be rolled back after an error without having to roll back the ** entire transaction. The statement transaction will automatically ** commit when the VDBE halts. ** +** If the database connection is currently in autocommit mode (that +** is to say, if it is in between BEGIN and COMMIT) +** and if there are no other active statements on the same database +** connection, then this operation is a no-op. No statement transaction +** is needed since any error can use the normal ROLLBACK process to +** undo changes. +** +** If a statement transaction is started, then a statement journal file +** will be allocated and initialized. +** ** The statement is begun on the database file with index P1. The main ** database file has an index of 0 and the file used for temporary tables ** has an index of 1. @@ -43057,14 +44604,10 @@ case OP_OpenWrite: { assert( p2>=2 ); } assert( i>=0 ); - pCur = allocateCursor(p, i, iDb); + pCur = allocateCursor(p, i, &pOp[-1], iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; - /* We always provide a key comparison function. If the table being - ** opened is of type INTKEY, the comparision function will be ignored. */ - rc = sqlite3BtreeCursor(pX, p2, wrFlag, - sqlite3VdbeRecordCompare, pOp->p4.p, - &pCur->pCursor); + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor); if( pOp->p4type==P4_KEYINFO ){ pCur->pKeyInfo = pOp->p4.pKeyInfo; pCur->pIncrKey = &pCur->pKeyInfo->incrKey; @@ -43107,6 +44650,7 @@ case OP_OpenWrite: { case SQLITE_EMPTY: { pCur->isTable = pOp->p4type!=P4_KEYINFO; pCur->isIndex = !pCur->isTable; + pCur->pCursor = 0; rc = SQLITE_OK; break; } @@ -43146,7 +44690,7 @@ case OP_OpenEphemeral: { SQLITE_OPEN_TRANSIENT_DB; assert( i>=0 ); - pCx = allocateCursor(p, i, -1); + pCx = allocateCursor(p, i, pOp, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags, @@ -43166,25 +44710,24 @@ case OP_OpenEphemeral: { rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_ZERODATA); if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); - rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare, - pOp->p4.z, &pCx->pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, + (KeyInfo*)pOp->p4.z, pCx->pCursor); pCx->pKeyInfo = pOp->p4.pKeyInfo; pCx->pKeyInfo->enc = ENC(p->db); pCx->pIncrKey = &pCx->pKeyInfo->incrKey; } pCx->isTable = 0; }else{ - rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); pCx->isTable = 1; pCx->pIncrKey = &pCx->bogusIncrKey; } } - pCx->nField = pOp->p2; pCx->isIndex = !pCx->isTable; break; } -/* Opcode: OpenPseudo P1 * * * * +/* Opcode: OpenPseudo P1 P2 * * * ** ** Open a new cursor that points to a fake table that contains a single ** row of data. Any attempt to write a second row of data causes the @@ -43195,15 +44738,24 @@ case OP_OpenEphemeral: { ** NEW or OLD tables in a trigger. Also used to hold the a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. +** +** When OP_Insert is executed to insert a row in to the pseudo table, +** the pseudo-table cursor may or may not make it's own copy of the +** original row data. If P2 is 0, then the pseudo-table will copy the +** original row data. Otherwise, a pointer to the original memory cell +** is stored. In this case, the vdbe program must ensure that the +** memory cell containing the row data is not overwritten until the +** pseudo table is closed (or a new row is inserted into it). */ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); - pCx = allocateCursor(p, i, -1); + pCx = allocateCursor(p, i, &pOp[-1], -1, 0); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTable = 1; + pCx->ephemPseudoTable = pOp->p2; pCx->pIncrKey = &pCx->bogusIncrKey; pCx->isTable = 1; pCx->isIndex = 0; @@ -43223,13 +44775,16 @@ case OP_Close: { break; } -/* Opcode: MoveGe P1 P2 P3 * * +/* Opcode: MoveGe P1 P2 P3 P4 * ** -** Use the value in register P3 as a key. Reposition -** cursor P1 so that it points to the smallest entry that is greater -** than or equal to the key in register P3. -** If there are no records greater than or equal to the key and P2 -** is not zero, then jump to P2. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than or equal to the key value. If there are no records +** greater than or equal to the key and P2 is not zero, then jump to P2. ** ** A special feature of this opcode (and different from the ** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is @@ -43240,33 +44795,42 @@ case OP_Close: { ** ** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe */ -/* Opcode: MoveGt P1 P2 P3 * * +/* Opcode: MoveGt P1 P2 P3 P4 * +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Use the value in register P3 as a key. Reposition -** cursor P1 so that it points to the smallest entry that is greater -** than the key in register P3. -** If there are no records greater than the key -** then jump to P2. +** Reposition cursor P1 so that it points to the smallest entry that +** is greater than the key value. If there are no records greater than +** the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe */ -/* Opcode: MoveLt P1 P2 P3 * * +/* Opcode: MoveLt P1 P2 P3 P4 * ** -** Use the value in register P3 as a key. Reposition -** cursor P1 so that it points to the largest entry that is less -** than the key in register P3. -** If there are no records less than the key -** then jump to P2. +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. +** +** Reposition cursor P1 so that it points to the largest entry that +** is less than the key value. If there are no records less than +** the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe */ -/* Opcode: MoveLe P1 P2 P3 * * +/* Opcode: MoveLe P1 P2 P3 P4 * +** +** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), +** use the integer value in register P3 as a key. If cursor P1 refers +** to an SQL index, then P3 is the first in an array of P4 registers +** that are used as an unpacked index key. ** -** Use the value in register P3 as a key. Reposition -** cursor P1 so that it points to the largest entry that is less than -** or equal to the key. -** If there are no records less than or eqal to the key -** then jump to P2. +** Reposition cursor P1 so that it points to the largest entry that +** is less than or equal to the key value. If there are no records +** less than or equal to the key and P2 is not zero, then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ @@ -43294,16 +44858,23 @@ case OP_MoveGt: { /* jump, in3 */ pC->deferredMoveto = 1; break; } - rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pC->lastRowid = iKey; pC->rowidIsValid = res==0; }else{ - assert( pIn3->flags & MEM_Blob ); - ExpandBlob(pIn3); - rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res); + UnpackedRecord r; + int nField = pOp->p4.i; + assert( pOp->p4type==P4_INT32 ); + assert( nField>0 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = nField; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p3]; + rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -43388,7 +44959,7 @@ case OP_Found: { /* jump, in3 */ if( pOp->opcode==OP_Found ){ pC->pKeyInfo->prefixIsEqual = 1; } - rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res); pC->pKeyInfo->prefixIsEqual = 0; if( rc!=SQLITE_OK ){ break; @@ -43465,7 +45036,7 @@ case OP_IsUnique: { /* jump, in3 */ */ assert( pCx->deferredMoveto==0 ); pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res); + rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -43476,7 +45047,7 @@ case OP_IsUnique: { /* jump, in3 */ break; } } - rc = sqlite3VdbeIdxKeyCompare(pCx, len, (u8*)zKey, &res); + rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res>0 ){ pc = pOp->p2 - 1; @@ -43533,7 +45104,7 @@ case OP_NotExists: { /* jump, in3 */ assert( pIn3->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pIn3->u.i); - rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res); + rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res); pC->lastRowid = pIn3->u.i; pC->rowidIsValid = res==0; pC->nullRow = 0; @@ -43698,12 +45269,12 @@ case OP_NewRowid: { /* out2-prerelease */ if( cnt==0 && (v&0xffffff)==v ){ v++; }else{ - sqlite3Randomness(sizeof(v), &v); + sqlite3_randomness(sizeof(v), &v); if( cnt<5 ) v &= 0xffffff; } if( v==0 ) continue; x = intToKey(v); - rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res); + rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res); cnt++; }while( cnt<100 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; @@ -43776,13 +45347,18 @@ case OP_Insert: { assert( pData->flags & (MEM_Blob|MEM_Str) ); } if( pC->pseudoTable ){ - sqlite3_free(pC->pData); + if( !pC->ephemPseudoTable ){ + sqlite3_free(pC->pData); + } pC->iKey = iKey; pC->nData = pData->n; - if( pData->flags & MEM_Dyn ){ + if( pData->z==pData->zMalloc || pC->ephemPseudoTable ){ pC->pData = pData->z; - pData->flags &= ~MEM_Dyn; - pData->flags |= MEM_Ephem; + if( !pC->ephemPseudoTable ){ + pData->flags &= ~MEM_Dyn; + pData->flags |= MEM_Ephem; + pData->zMalloc = 0; + } }else{ pC->pData = sqlite3_malloc( pC->nData+2 ); if( !pC->pData ) goto no_mem; @@ -43935,13 +45511,13 @@ case OP_RowData: { i64 n64; assert( !pC->isTable ); sqlite3BtreeKeySize(pCrsr, &n64); - if( n64>SQLITE_MAX_LENGTH ){ + if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } n = n64; }else{ sqlite3BtreeDataSize(pCrsr, &n); - if( n>SQLITE_MAX_LENGTH ){ + if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } } @@ -44176,22 +45752,29 @@ case OP_IdxInsert: { /* in2 */ break; } -/* Opcode: IdxDelete P1 P2 * * * +/* Opcode: IdxDeleteM P1 P2 P3 * * ** -** The content of register P2 is an index key built using the -** MakeIdxRec opcode. This opcode removes that entry from the +** The content of P3 registers starting at register P2 form +** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. */ -case OP_IdxDelete: { /* in2 */ +case OP_IdxDelete: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; - assert( pIn2->flags & MEM_Blob ); + assert( pOp->p3>0 ); + assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem ); assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res; - rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res); + UnpackedRecord r; + r.pKeyInfo = pC->pKeyInfo; + r.nField = pOp->p3; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p2]; + rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } @@ -44233,35 +45816,31 @@ case OP_IdxRowid: { /* out2-prerelease */ break; } -/* Opcode: IdxGE P1 P2 P3 * P5 +/* Opcode: IdxGE P1 P2 P3 P4 P5 ** -** The value in register P3 is an index entry that omits the ROWID. Compare -** this value against the index that P1 is currently pointing to. -** Ignore the ROWID on the P1 index. +** The P4 register values beginning with P3 form an unpacked index +** key that omits the ROWID. Compare this key value against the index +** that P1 is currently pointing to, ignoring the ROWID on the P1 index. ** -** If the P1 index entry is greater than or equal to the value in -** register P3 then jump to P2. Otherwise fall through to the next -** instruction. +** If the P1 index entry is greater than or equal to the key value +** then jump to P2. Otherwise fall through to the next instruction. ** -** If P5 is non-zero then the value in register P3 is temporarily -** increased by an epsilon prior to the comparison. This make the opcode work -** like IdxGT except that if the key from register P3 is a prefix of -** the key in the cursor, the result is false whereas it would be -** true with IdxGT. +** If P5 is non-zero then the key value is increased by an epsilon +** prior to the comparison. This make the opcode work like IdxGT except +** that if the key from register P3 is a prefix of the key in the cursor, +** the result is false whereas it would be true with IdxGT. */ /* Opcode: IdxLT P1 P2 P3 * P5 ** -** The value in register P3 is an index entry that omits the ROWID. Compare -** the this value against the index that P1 is currently pointing to. -** Ignore the ROWID on the P1 index. +** The P4 register values beginning with P3 form an unpacked index +** key that omits the ROWID. Compare this key value against the index +** that P1 is currently pointing to, ignoring the ROWID on the P1 index. ** -** If the P1 index entry is less than the register P3 value -** then jump to P2. Otherwise fall through to the next instruction. +** If the P1 index entry is less than the key value then jump to P2. +** Otherwise fall through to the next instruction. ** -** If P5 is non-zero then the -** index taken from register P3 is temporarily increased by -** an epsilon prior to the comparison. This makes the opcode work -** like IdxLE. +** If P5 is non-zero then the key value is increased by an epsilon prior +** to the comparison. This makes the opcode work like IdxLE. */ case OP_IdxLT: /* jump, in3 */ case OP_IdxGE: { /* jump, in3 */ @@ -44272,17 +45851,18 @@ case OP_IdxGE: { /* jump, in3 */ assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ int res; - - assert( pIn3->flags & MEM_Blob ); /* Created using OP_MakeRecord */ + UnpackedRecord r; assert( pC->deferredMoveto==0 ); - ExpandBlob(pIn3); assert( pOp->p5==0 || pOp->p5==1 ); + assert( pOp->p4type==P4_INT32 ); + r.pKeyInfo = pC->pKeyInfo; + r.nField = pOp->p4.i; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p3]; *pC->pIncrKey = pOp->p5; - rc = sqlite3VdbeIdxKeyCompare(pC, pIn3->n, (u8*)pIn3->z, &res); + rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res); *pC->pIncrKey = 0; - if( rc!=SQLITE_OK ){ - break; - } if( pOp->opcode==OP_IdxLT ){ res = -res; }else{ @@ -44737,6 +46317,7 @@ case OP_AggStep: { pMem->n++; ctx.s.flags = MEM_Null; ctx.s.z = 0; + ctx.s.zMalloc = 0; ctx.s.xDel = 0; ctx.s.db = db; ctx.isError = 0; @@ -44777,6 +46358,7 @@ case OP_AggFinal: { if( rc==SQLITE_ERROR ){ sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0); } + sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); if( sqlite3VdbeMemTooBig(pMem) ){ goto too_big; @@ -44841,16 +46423,14 @@ case OP_Expire: { } #ifndef SQLITE_OMIT_SHARED_CACHE -/* Opcode: TableLock P1 P2 * P4 * +/* Opcode: TableLock P1 P2 P3 P4 * ** ** Obtain a lock on a particular table. This instruction is only used when ** the shared-cache feature is enabled. ** -** If P1 is not negative, then it is the index of the database -** in sqlite3.aDb[] and a read-lock is required. If P1 is negative, a -** write-lock is required. In this case the index of the database is the -** absolute value of P1 minus one (iDb = abs(P1) - 1;) and a write-lock is -** required. +** If P1 is the index of the database in sqlite3.aDb[] of the database +** on which the lock is acquired. A readlock is obtained if P3==0 or +** a write lock if P3==1. ** ** P2 contains the root-page of the table to lock. ** @@ -44859,12 +46439,10 @@ case OP_Expire: { */ case OP_TableLock: { int p1 = pOp->p1; - u8 isWriteLock = (p1<0); - if( isWriteLock ){ - p1 = (-1*p1)-1; - } + u8 isWriteLock = pOp->p3; assert( p1>=0 && p1nDb ); assert( (p->btreeMask & (1<aDb[p1].pBt, pOp->p2, isWriteLock); if( rc==SQLITE_LOCKED ){ const char *z = pOp->p4.z; @@ -44935,7 +46513,7 @@ case OP_VOpen: { pVtabCursor->pVtab = pVtab; /* Initialise vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, -1); + pCur = allocateCursor(p, pOp->p1, &pOp[-1], -1, 0); if( pCur ){ pCur->pVtabCursor = pVtabCursor; pCur->pModule = pVtabCursor->pVtab->pModule; @@ -45212,6 +46790,7 @@ case OP_VUpdate: { assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) ); db->lastRowid = rowid; } + p->nChange++; } break; } @@ -45370,7 +46949,7 @@ abort_due_to_interrupt: ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.20 2008/01/25 15:04:50 drh Exp $ +** $Id: vdbeblob.c,v 1.22 2008/04/24 09:49:55 danielk1977 Exp $ */ @@ -45426,16 +47005,17 @@ SQLITE_API int sqlite3_blob_open( /* One of the following two instructions is replaced by an ** OP_Noop before exection. */ - {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ - {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ + {OP_SetNumColumns, 0, 0, 0}, /* 2: Num cols for cursor */ + {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ {OP_SetNumColumns, 0, 0, 0}, /* 4: Num cols for cursor */ - - {OP_Variable, 1, 1, 0}, /* 5: Push the rowid to the stack */ - {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */ - {OP_Column, 0, 0, 1}, /* 7 */ - {OP_ResultRow, 1, 0, 0}, /* 8 */ - {OP_Close, 0, 0, 0}, /* 9 */ - {OP_Halt, 0, 0, 0}, /* 10 */ + {OP_OpenWrite, 0, 0, 0}, /* 5: Open cursor 0 for read/write */ + + {OP_Variable, 1, 1, 0}, /* 6: Push the rowid to the stack */ + {OP_NotExists, 0, 10, 1}, /* 7: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 8 */ + {OP_ResultRow, 1, 0, 0}, /* 9 */ + {OP_Close, 0, 0, 0}, /* 10 */ + {OP_Halt, 0, 0, 0}, /* 11 */ }; Vdbe *v = 0; @@ -45459,6 +47039,16 @@ SQLITE_API int sqlite3_blob_open( sqlite3BtreeEnterAll(db); pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb); + if( pTab && IsVirtual(pTab) ){ + pTab = 0; + sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable); + } +#ifndef SQLITE_OMIT_VIEW + if( pTab && pTab->pSelect ){ + pTab = 0; + sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable); + } +#endif if( !pTab ){ if( sParse.zErrMsg ){ sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg); @@ -45524,9 +47114,9 @@ SQLITE_API int sqlite3_blob_open( /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ - sqlite3VdbeChangeToNoop(v, (flags ? 2 : 3), 1); - sqlite3VdbeChangeP2(v, (flags ? 3 : 2), pTab->tnum); - sqlite3VdbeChangeP3(v, (flags ? 3 : 2), iDb); + sqlite3VdbeChangeToNoop(v, (flags ? 3 : 5), 1); + sqlite3VdbeChangeP2(v, (flags ? 5 : 3), pTab->tnum); + sqlite3VdbeChangeP3(v, (flags ? 5 : 3), iDb); /* Configure the OP_SetNumColumns. Configure the cursor to ** think that the table has one more column than it really @@ -45535,7 +47125,7 @@ SQLITE_API int sqlite3_blob_open( ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ - sqlite3VdbeChangeP2(v, 4, pTab->nCol+1); + sqlite3VdbeChangeP2(v, flags ? 4 : 2, pTab->nCol+1); if( !db->mallocFailed ){ sqlite3VdbeMakeReady(v, 1, 1, 1, 0); } @@ -45706,7 +47296,7 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){ ** ************************************************************************* ** -** @(#) $Id: journal.c,v 1.7 2007/09/06 13:49:37 drh Exp $ +** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $ */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE @@ -45844,9 +47434,10 @@ static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ static int jrnlSync(sqlite3_file *pJfd, int flags){ int rc; JournalFile *p = (JournalFile *)pJfd; - rc = createFile(p); - if( rc==SQLITE_OK ){ + if( p->pReal ){ rc = sqlite3OsSync(p->pReal, flags); + }else{ + rc = SQLITE_OK; } return rc; } @@ -45948,7 +47539,7 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.354 2008/03/12 10:39:00 danielk1977 Exp $ +** $Id: expr.c,v 1.371 2008/05/01 17:16:53 drh Exp $ */ /* @@ -46136,6 +47727,30 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq( } /* +** Generate the operands for a comparison operation. Before +** generating the code for each operand, set the EP_AnyAff +** flag on the expression so that it will be able to used a +** cached column value that has previously undergone an +** affinity change. +*/ +static void codeCompareOperands( + Parse *pParse, /* Parsing and code generating context */ + Expr *pLeft, /* The left operand */ + int *pRegLeft, /* Register where left operand is stored */ + int *pFreeLeft, /* Free this register when done */ + Expr *pRight, /* The right operand */ + int *pRegRight, /* Register where right operand is stored */ + int *pFreeRight /* Write temp register for right operand there */ +){ + while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft; + pLeft->flags |= EP_AnyAff; + *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft); + while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft; + pRight->flags |= EP_AnyAff; + *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight); +} + +/* ** Generate code for a comparison operator. */ static int codeCompare( @@ -46156,6 +47771,10 @@ static int codeCompare( addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, (void*)p4, P4_COLLSEQ); sqlite3VdbeChangeP5(pParse->pVdbe, p5); + if( p5 & SQLITE_AFF_MASK ){ + sqlite3ExprCacheAffinityChange(pParse, in1, 1); + sqlite3ExprCacheAffinityChange(pParse, in2, 1); + } return addr; } @@ -46334,9 +47953,13 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ ** use it as the variable number */ int i; pExpr->iTable = i = atoi((char*)&pToken->z[1]); - if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ + testcase( i==0 ); + testcase( i==1 ); + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 ); + testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ); + if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", - SQLITE_MAX_VARIABLE_NUMBER); + db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); } if( i>pParse->nVar ){ pParse->nVar = i; @@ -46374,7 +47997,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ } } } - if( !pParse->nErr && pParse->nVar>SQLITE_MAX_VARIABLE_NUMBER ){ + if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); } } @@ -46630,16 +48253,17 @@ no_mem: SQLITE_PRIVATE void sqlite3ExprListCheckLength( Parse *pParse, ExprList *pEList, - int iLimit, const char *zObject ){ - if( pEList && pEList->nExpr>iLimit ){ + int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; + testcase( pEList && pEList->nExpr==mx ); + testcase( pEList && pEList->nExpr==mx+1 ); + if( pEList && pEList->nExpr>mx ){ sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); } } -#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 /* The following three functions, heightOfExpr(), heightOfExprList() ** and heightOfSelect(), are used to determine the maximum height ** of any expression tree referenced by the structure passed as the @@ -46702,7 +48326,6 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){ heightOfSelect(p, &nHeight); return nHeight; } -#endif /* ** Delete an entire expression list. @@ -46722,7 +48345,8 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(ExprList *pList){ } /* -** Walk an expression tree. Call xFunc for each node visited. +** Walk an expression tree. Call xFunc for each node visited. xFunc +** is called on the node before xFunc is called on the nodes children. ** ** The return value from xFunc determines whether the tree walk continues. ** 0 means continue walking the tree. 1 means do not walk children @@ -46816,7 +48440,14 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){ #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: -#endif + testcase( pExpr->op==TK_SELECT ); + testcase( pExpr->op==TK_EXISTS ); +#endif + testcase( pExpr->op==TK_ID ); + testcase( pExpr->op==TK_COLUMN ); + testcase( pExpr->op==TK_DOT ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + testcase( pExpr->op==TK_AGG_COLUMN ); *pN = 0; return 2; case TK_IN: @@ -47072,6 +48703,8 @@ static int lookupName( } pExpr->pTab = pTab; if( iCol>=0 ){ + testcase( iCol==31 ); + testcase( iCol==32 ); *piColMask |= ((u32)1<=32?0xffffffff:0); } break; @@ -47181,6 +48814,7 @@ static int lookupName( */ if( pExpr->iColumn>=0 && pMatch!=0 ){ int n = pExpr->iColumn; + testcase( n==sizeof(Bitmask)*8-1 ); if( n>=sizeof(Bitmask)*8 ){ n = sizeof(Bitmask)*8-1; } @@ -47418,21 +49052,24 @@ SQLITE_PRIVATE int sqlite3ExprResolveNames( Expr *pExpr /* The expression to be analyzed. */ ){ int savedHasAgg; + if( pExpr==0 ) return 0; -#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 - if( (pExpr->nHeight+pNC->pParse->nHeight)>SQLITE_MAX_EXPR_DEPTH ){ - sqlite3ErrorMsg(pNC->pParse, - "Expression tree is too large (maximum depth %d)", - SQLITE_MAX_EXPR_DEPTH - ); - return 1; +#if SQLITE_MAX_EXPR_DEPTH>0 + { + int mxDepth = pNC->pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH]; + if( (pExpr->nHeight+pNC->pParse->nHeight)>mxDepth ){ + sqlite3ErrorMsg(pNC->pParse, + "Expression tree is too large (maximum depth %d)", mxDepth + ); + return 1; + } + pNC->pParse->nHeight += pExpr->nHeight; } - pNC->pParse->nHeight += pExpr->nHeight; #endif savedHasAgg = pNC->hasAgg; pNC->hasAgg = 0; walkExprTree(pExpr, nameResolverStep, pNC); -#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 +#if SQLITE_MAX_EXPR_DEPTH>0 pNC->pParse->nHeight -= pExpr->nHeight; #endif if( pNC->nErr>0 ){ @@ -47463,6 +49100,45 @@ struct QueryCoder { #endif /* +** Return true if the IN operator optimization is enabled and +** the SELECT statement p exists and is of the +** simple form: +** +** SELECT FROM +** +** If this is the case, it may be possible to use an existing table +** or index instead of generating an epheremal table. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +static int isCandidateForInOpt(Select *p){ + SrcList *pSrc; + ExprList *pEList; + Table *pTab; + if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */ + if( p==0 ) return 0; /* right-hand side of IN is SELECT */ + if( p->pPrior ) return 0; /* Not a compound SELECT */ + if( p->isDistinct ) return 0; /* No DISTINCT keyword */ + if( p->isAgg ) return 0; /* Contains no aggregate functions */ + if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */ + if( p->pLimit ) return 0; /* Has no LIMIT clause */ + if( p->pOffset ) return 0; + if( p->pWhere ) return 0; /* Has no WHERE clause */ + pSrc = p->pSrc; + if( pSrc==0 ) return 0; /* A single table in the FROM clause */ + if( pSrc->nSrc!=1 ) return 0; + if( pSrc->a[0].pSelect ) return 0; /* FROM clause is not a subquery */ + pTab = pSrc->a[0].pTab; + if( pTab==0 ) return 0; + if( pTab->pSelect ) return 0; /* FROM clause is not a view */ + if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */ + pEList = p->pEList; + if( pEList->nExpr!=1 ) return 0; /* One column in the result set */ + if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */ + return 1; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +/* ** This function is used by the implementation of the IN (...) operator. ** It's job is to find or create a b-tree structure that may be used ** either to test for membership of the (...) set or to iterate through @@ -47507,14 +49183,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique) ** If this is the case, it may be possible to use an existing table ** or index instead of generating an epheremal table. */ - if( sqlite3_enable_in_opt - && (p=pX->pSelect)!=0 && !p->pPrior - && !p->isDistinct && !p->isAgg && !p->pGroupBy - && p->pSrc && p->pSrc->nSrc==1 && !p->pSrc->a[0].pSelect - && p->pSrc->a[0].pTab && !p->pSrc->a[0].pTab->pSelect - && p->pEList->nExpr==1 && p->pEList->a[0].pExpr->op==TK_COLUMN - && !p->pLimit && !p->pOffset && !p->pWhere - ){ + p = pX->pSelect; + if( isCandidateForInOpt(p) ){ sqlite3 *db = pParse->db; Index *pIdx; Expr *pExpr = p->pEList->a[0].pExpr; @@ -47572,11 +49242,11 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique) iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIdx->nColumn); sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); eType = IN_INDEX_INDEX; - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iTab, pIdx->nColumn); sqlite3VdbeJumpHere(v, iAddr); } @@ -47652,10 +49322,9 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp1(v, OP_OpenEphemeral, pExpr->iTable); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; - sqlite3VdbeAddOp2(v, OP_SetNumColumns, pExpr->iTable, 1); if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) @@ -47712,8 +49381,12 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ } /* Evaluate the expression and insert it into the temp table */ + pParse->disableColCache++; sqlite3ExprCode(pParse, pE2, r1); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); } sqlite3ReleaseTempReg(pParse, r1); @@ -47788,9 +49461,13 @@ static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){ char *zV; assert( !isdigit(z[n]) ); sqlite3AtoF(z, &value); - if( negateFlag ) value = -value; - zV = dup8bytes(v, (char*)&value); - sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); + if( sqlite3IsNaN(value) ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, iMem); + }else{ + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); + } } } @@ -47827,17 +49504,42 @@ static void codeInteger(Vdbe *v, const char *z, int n, int negFlag, int iMem){ /* ** Generate code that will extract the iColumn-th column from -** table pTab and store the column value in register iReg. -** There is an open cursor to pTab in -** iTable. If iColumn<0 then code is generated that extracts the rowid. +** table pTab and store the column value in a register. An effort +** is made to store the column value in register iReg, but this is +** not guaranteed. The location of the column value is returned. +** +** There must be an open cursor to pTab in iTable when this routine +** is called. If iColumn<0 then code is generated that extracts the rowid. +** +** This routine might attempt to reuse the value of the column that +** has already been loaded into a register. The value will always +** be used if it has not undergone any affinity changes. But if +** an affinity change has occurred, then the cached value will only be +** used if allowAffChng is true. */ -SQLITE_PRIVATE void sqlite3ExprCodeGetColumn( - Vdbe *v, /* The VM being created */ +SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( + Parse *pParse, /* Parsing and code generating context */ Table *pTab, /* Description of the table we are reading from */ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ - int iReg /* Store results here */ + int iReg, /* Store results here */ + int allowAffChng /* True if prior affinity changes are OK */ ){ + Vdbe *v = pParse->pVdbe; + int i; + struct yColCache *p; + + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + if( p->iTable==iTable && p->iColumn==iColumn + && (!p->affChange || allowAffChng) ){ +#if 0 + sqlite3VdbeAddOp0(v, OP_Noop); + VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg)); +#endif + return p->iReg; + } + } + assert( v!=0 ); if( iColumn<0 ){ int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; sqlite3VdbeAddOp2(v, op, iTable, iReg); @@ -47853,6 +49555,131 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumn( } #endif } + if( pParse->disableColCache==0 ){ + i = pParse->iColCache; + p = &pParse->aColCache[i]; + p->iTable = iTable; + p->iColumn = iColumn; + p->iReg = iReg; + p->affChange = 0; + i++; + if( i>=ArraySize(pParse->aColCache) ) i = 0; + if( i>pParse->nColCache ) pParse->nColCache = i; + pParse->iColCache = i; + } + return iReg; +} + +/* +** Clear all column cache entries associated with the vdbe +** cursor with cursor number iTable. +*/ +SQLITE_PRIVATE void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){ + if( iTable<0 ){ + pParse->nColCache = 0; + pParse->iColCache = 0; + }else{ + int i; + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].iTable==iTable ){ + testcase( i==pParse->nColCache-1 ); + pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; + pParse->iColCache = pParse->nColCache; + } + } + } +} + +/* +** Record the fact that an affinity change has occurred on iCount +** registers starting with iStart. +*/ +SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ + int iEnd = iStart + iCount - 1; + int i; + for(i=0; inColCache; i++){ + int r = pParse->aColCache[i].iReg; + if( r>=iStart && r<=iEnd ){ + pParse->aColCache[i].affChange = 1; + } + } +} + +/* +** Generate code to moves content from one register to another. +** Keep the column cache up-to-date. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo){ + int i; + if( iFrom==iTo ) return; + sqlite3VdbeAddOp2(pParse->pVdbe, OP_Move, iFrom, iTo); + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].iReg==iFrom ){ + pParse->aColCache[i].iReg = iTo; + } + } +} + +/* +** Return true if any register in the range iFrom..iTo (inclusive) +** is used as part of the column cache. +*/ +static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ + int i; + for(i=0; inColCache; i++){ + int r = pParse->aColCache[i].iReg; + if( r>=iFrom && r<=iTo ) return 1; + } + return 0; +} + +/* +** Theres is a value in register iCurrent. We ultimately want +** the value to be in register iTarget. It might be that +** iCurrent and iTarget are the same register. +** +** We are going to modify the value, so we need to make sure it +** is not a cached register. If iCurrent is a cached register, +** then try to move the value over to iTarget. If iTarget is a +** cached register, then clear the corresponding cache line. +** +** Return the register that the value ends up in. +*/ +SQLITE_PRIVATE int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){ + int i; + assert( pParse->pVdbe!=0 ); + if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){ + return iCurrent; + } + if( iCurrent!=iTarget ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget); + } + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].iReg==iTarget ){ + pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; + pParse->iColCache = pParse->nColCache; + } + } + return iTarget; +} + +/* +** If the last instruction coded is an ephemeral copy of any of +** the registers in the nReg registers beginning with iReg, then +** convert the last instruction from OP_SCopy to OP_Copy. +*/ +SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ + int addr; + VdbeOp *pOp; + Vdbe *v; + + v = pParse->pVdbe; + addr = sqlite3VdbeCurrentAddr(v); + pOp = sqlite3VdbeGetOp(v, addr-1); + assert( pOp || pParse->db->mallocFailed ); + if( pOp && pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1opcode = OP_Copy; + } } /* @@ -47866,13 +49693,13 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumn( ** must check the return code and move the results to the desired ** register. */ -static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ +SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ Vdbe *v = pParse->pVdbe; /* The VM under construction */ int op; /* The opcode being coded */ int inReg = target; /* Results stored in register inReg */ int regFree1 = 0; /* If non-zero free this temporary register */ int regFree2 = 0; /* If non-zero free this temporary register */ - int r1, r2, r3; /* Various register numbers */ + int r1, r2, r3, r4; /* Various register numbers */ assert( v!=0 || pParse->db->mallocFailed ); assert( target>0 && target<=pParse->nMem ); @@ -47904,8 +49731,10 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( pParse->ckBase>0 ); inReg = pExpr->iColumn + pParse->ckBase; }else{ - sqlite3ExprCodeGetColumn(v, pExpr->pTab, - pExpr->iColumn, pExpr->iTable, target); + testcase( (pExpr->flags & EP_AnyAff)!=0 ); + inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + pExpr->iColumn, pExpr->iTable, target, + pExpr->flags & EP_AnyAff); } break; } @@ -47966,7 +49795,14 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); + testcase( to_op==OP_ToText ); + testcase( to_op==OP_ToBlob ); + testcase( to_op==OP_ToNumeric ); + testcase( to_op==OP_ToInt ); + testcase( to_op==OP_ToReal ); sqlite3VdbeAddOp1(v, to_op, inReg); + testcase( usedAsColumnCache(pParse, inReg, inReg) ); + sqlite3ExprCacheAffinityChange(pParse, inReg, 1); break; } #endif /* SQLITE_OMIT_CAST */ @@ -47982,10 +49818,18 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( TK_GE==OP_Ge ); assert( TK_EQ==OP_Eq ); assert( TK_NE==OP_Ne ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + testcase( op==TK_LT ); + testcase( op==TK_LE ); + testcase( op==TK_GT ); + testcase( op==TK_GE ); + testcase( op==TK_EQ ); + testcase( op==TK_NE ); + codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, + pExpr->pRight, &r2, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2); + testcase( regFree1==0 ); + testcase( regFree2==0 ); break; } case TK_AND: @@ -48011,9 +49855,22 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( TK_LSHIFT==OP_ShiftLeft ); assert( TK_RSHIFT==OP_ShiftRight ); assert( TK_CONCAT==OP_Concat ); + testcase( op==TK_AND ); + testcase( op==TK_OR ); + testcase( op==TK_PLUS ); + testcase( op==TK_MINUS ); + testcase( op==TK_REM ); + testcase( op==TK_BITAND ); + testcase( op==TK_BITOR ); + testcase( op==TK_SLASH ); + testcase( op==TK_LSHIFT ); + testcase( op==TK_RSHIFT ); + testcase( op==TK_CONCAT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); sqlite3VdbeAddOp3(v, op, r2, r1, target); + testcase( regFree1==0 ); + testcase( regFree2==0 ); break; } case TK_UMINUS: { @@ -48029,8 +49886,9 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ }else{ regFree1 = r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); - r2 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); + testcase( regFree2==0 ); } inReg = target; break; @@ -48039,7 +49897,12 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_NOT: { assert( TK_BITNOT==OP_BitNot ); assert( TK_NOT==OP_Not ); + testcase( op==TK_BITNOT ); + testcase( op==TK_NOT ); inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + testcase( inReg==target ); + testcase( usedAsColumnCache(pParse, inReg, inReg) ); + inReg = sqlite3ExprWritableRegister(pParse, inReg, target); sqlite3VdbeAddOp1(v, op, inReg); break; } @@ -48048,8 +49911,11 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ int addr; assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); + testcase( op==TK_ISNULL ); + testcase( op==TK_NOTNULL ); sqlite3VdbeAddOp2(v, OP_Integer, 1, target); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); addr = sqlite3VdbeAddOp1(v, op, r1); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeJumpHere(v, addr); @@ -48078,6 +49944,8 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ u8 enc = ENC(db); CollSeq *pColl = 0; + testcase( op==TK_CONST_FUNC ); + testcase( op==TK_FUNCTION ); zId = (char*)pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); @@ -48085,7 +49953,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pList ){ nExpr = pList->nExpr; r1 = sqlite3GetTempRange(pParse, nExpr); - sqlite3ExprCodeExprList(pParse, pList, r1); + sqlite3ExprCodeExprList(pParse, pList, r1, 1); }else{ nExpr = r1 = 0; } @@ -48126,11 +49994,14 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( nExpr ){ sqlite3ReleaseTempRange(pParse, r1, nExpr); } + sqlite3ExprCacheAffinityChange(pParse, r1, nExpr); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { + testcase( op==TK_EXISTS ); + testcase( op==TK_SELECT ); if( pExpr->iColumn==0 ){ sqlite3CodeSubselect(pParse, pExpr); } @@ -48156,12 +50027,13 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ ** pExpr->iTable contains the values that make up the (...) set. */ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); sqlite3VdbeAddOp2(v, OP_Null, 0, target); j2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j1); if( eType==IN_INDEX_ROWID ){ - j3 = sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, 0, 1); + j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, r1); j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1); j5 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, j3); @@ -48169,6 +50041,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ }else{ r2 = regFree2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, r1, 1); j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2); } sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); @@ -48193,18 +50066,23 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ struct ExprList_item *pLItem = pExpr->pList->a; Expr *pRight = pLItem->pExpr; - r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); + codeCompareOperands(pParse, pLeft, &r1, ®Free1, + pRight, &r2, ®Free2); + testcase( regFree1==0 ); + testcase( regFree2==0 ); r3 = sqlite3GetTempReg(pParse); + r4 = sqlite3GetTempReg(pParse); codeCompare(pParse, pLeft, pRight, OP_Ge, r1, r2, r3, SQLITE_STOREP2); pLItem++; pRight = pLItem->pExpr; sqlite3ReleaseTempReg(pParse, regFree2); r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); - codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r2, SQLITE_STOREP2); - sqlite3VdbeAddOp3(v, OP_And, r3, r2, target); + testcase( regFree2==0 ); + codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); + sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); + sqlite3ReleaseTempReg(pParse, r4); break; } case TK_UPLUS: { @@ -48254,12 +50132,16 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ endLabel = sqlite3VdbeMakeLabel(v); if( (pX = pExpr->pLeft)!=0 ){ cacheX = *pX; + testcase( pX->op==TK_COLUMN || pX->op==TK_REGISTER ); cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); + testcase( regFree1==0 ); cacheX.op = TK_REGISTER; + cacheX.iColumn = 0; opCompare.op = TK_EQ; opCompare.pLeft = &cacheX; pTest = &opCompare; } + pParse->disableColCache++; for(i=0; iop==TK_COLUMN || pTest->op==TK_REGISTER ); sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); + testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); + testcase( aListelem[i+1].pExpr->op==TK_REGISTER ); sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); sqlite3VdbeResolveLabel(v, nextCase); @@ -48278,6 +50163,8 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } sqlite3VdbeResolveLabel(v, endLabel); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; break; } #ifndef SQLITE_OMIT_TRIGGER @@ -48315,7 +50202,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ ** are stored. ** ** If the register is a temporary register that can be deallocated, -** then write its number into *pReg. If the result register is no +** then write its number into *pReg. If the result register is not ** a temporary, then set *pReg to zero. */ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ @@ -48369,11 +50256,123 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe iMem = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); pExpr->iTable = iMem; + pExpr->iColumn = pExpr->op; pExpr->op = TK_REGISTER; } return inReg; } +/* +** Return TRUE if pExpr is an constant expression that is appropriate +** for factoring out of a loop. Appropriate expressions are: +** +** * Any expression that evaluates to two or more opcodes. +** +** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null, +** or OP_Variable that does not need to be placed in a +** specific register. +** +** There is no point in factoring out single-instruction constant +** expressions that need to be placed in a particular register. +** We could factor them out, but then we would end up adding an +** OP_SCopy instruction to move the value into the correct register +** later. We might as well just use the original instruction and +** avoid the OP_SCopy. +*/ +static int isAppropriateForFactoring(Expr *p){ + if( !sqlite3ExprIsConstantNotJoin(p) ){ + return 0; /* Only constant expressions are appropriate for factoring */ + } + if( (p->flags & EP_FixedDest)==0 ){ + return 1; /* Any constant without a fixed destination is appropriate */ + } + while( p->op==TK_UPLUS ) p = p->pLeft; + switch( p->op ){ +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: +#endif + case TK_VARIABLE: + case TK_INTEGER: + case TK_FLOAT: + case TK_NULL: + case TK_STRING: { + testcase( p->op==TK_BLOB ); + testcase( p->op==TK_VARIABLE ); + testcase( p->op==TK_INTEGER ); + testcase( p->op==TK_FLOAT ); + testcase( p->op==TK_NULL ); + testcase( p->op==TK_STRING ); + /* Single-instruction constants with a fixed destination are + ** better done in-line. If we factor them, they will just end + ** up generating an OP_SCopy to move the value to the destination + ** register. */ + return 0; + } + case TK_UMINUS: { + if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){ + return 0; + } + break; + } + default: { + break; + } + } + return 1; +} + +/* +** If pExpr is a constant expression that is appropriate for +** factoring out of a loop, then evaluate the expression +** into a register and convert the expression into a TK_REGISTER +** expression. +*/ +static int evalConstExpr(void *pArg, Expr *pExpr){ + Parse *pParse = (Parse*)pArg; + switch( pExpr->op ){ + case TK_REGISTER: { + return 1; + } + case TK_FUNCTION: + case TK_AGG_FUNCTION: + case TK_CONST_FUNC: { + /* The arguments to a function have a fixed destination. + ** Mark them this way to avoid generated unneeded OP_SCopy + ** instructions. + */ + ExprList *pList = pExpr->pList; + if( pList ){ + int i = pList->nExpr; + struct ExprList_item *pItem = pList->a; + for(; i>0; i--, pItem++){ + if( pItem->pExpr ) pItem->pExpr->flags |= EP_FixedDest; + } + } + break; + } + } + if( isAppropriateForFactoring(pExpr) ){ + int r1 = ++pParse->nMem; + int r2; + r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); + if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1); + pExpr->iColumn = pExpr->op; + pExpr->op = TK_REGISTER; + pExpr->iTable = r2; + return 1; + } + return 0; +} + +/* +** Preevaluate constant subexpressions within pExpr and store the +** results in registers. Modify pExpr so that the constant subexpresions +** are TK_REGISTER opcodes that refer to the precomputed values. +*/ +SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){ + walkExprTree(pExpr, evalConstExpr, pParse); +} + /* ** Generate code that pushes the value of every element of the given @@ -48384,7 +50383,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe SQLITE_PRIVATE int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ - int target /* Where to write results */ + int target, /* Where to write results */ + int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */ ){ struct ExprList_item *pItem; int i, n; @@ -48394,9 +50394,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( } assert( target>0 ); n = pList->nExpr; - for(pItem=pList->a, i=n; i>0; i--, pItem++){ - sqlite3ExprCode(pParse, pItem->pExpr, target); - target++; + for(pItem=pList->a, i=0; ipExpr, target+i); + if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n); } return n; } @@ -48428,17 +50428,28 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int switch( op ){ case TK_AND: { int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); + pParse->disableColCache++; sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; sqlite3VdbeResolveLabel(v, d2); break; } case TK_OR: { + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + pParse->disableColCache++; sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; break; } case TK_NOT: { + testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } @@ -48454,18 +50465,30 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int assert( TK_GE==OP_Ge ); assert( TK_EQ==OP_Eq ); assert( TK_NE==OP_Ne ); - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + testcase( op==TK_LT ); + testcase( op==TK_LE ); + testcase( op==TK_GT ); + testcase( op==TK_GE ); + testcase( op==TK_EQ ); + testcase( op==TK_NE ); + testcase( jumpIfNull==0 ); + codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, + pExpr->pRight, &r2, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); + testcase( regFree1==0 ); + testcase( regFree2==0 ); break; } case TK_ISNULL: case TK_NOTNULL: { assert( TK_ISNULL==OP_IsNull ); assert( TK_NOTNULL==OP_NotNull ); + testcase( op==TK_ISNULL ); + testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( regFree1==0 ); break; } case TK_BETWEEN: { @@ -48494,13 +50517,17 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int compRight.pLeft = &exprX; compRight.pRight = pExpr->pList->a[1].pExpr; exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); + testcase( regFree1==0 ); exprX.op = TK_REGISTER; + testcase( jumpIfNull==0 ); sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); break; } default: { r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); break; } } @@ -48560,14 +50587,24 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int switch( pExpr->op ){ case TK_AND: { + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + pParse->disableColCache++; sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; break; } case TK_OR: { int d2 = sqlite3VdbeMakeLabel(v); + testcase( jumpIfNull==0 ); + testcase( pParse->disableColCache==0 ); sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); + pParse->disableColCache++; sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + assert( pParse->disableColCache>0 ); + pParse->disableColCache--; sqlite3VdbeResolveLabel(v, d2); break; } @@ -48581,16 +50618,28 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int case TK_GE: case TK_NE: case TK_EQ: { - r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); - r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + testcase( op==TK_LT ); + testcase( op==TK_LE ); + testcase( op==TK_GT ); + testcase( op==TK_GE ); + testcase( op==TK_EQ ); + testcase( op==TK_NE ); + testcase( jumpIfNull==0 ); + codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1, + pExpr->pRight, &r2, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); + testcase( regFree1==0 ); + testcase( regFree2==0 ); break; } case TK_ISNULL: case TK_NOTNULL: { + testcase( op==TK_ISNULL ); + testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); sqlite3VdbeAddOp2(v, op, r1, dest); + testcase( regFree1==0 ); break; } case TK_BETWEEN: { @@ -48619,13 +50668,17 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int compRight.pLeft = &exprX; compRight.pRight = pExpr->pList->a[1].pExpr; exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); + testcase( regFree1==0 ); exprX.op = TK_REGISTER; + testcase( jumpIfNull==0 ); sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); break; } default: { r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); + testcase( regFree1==0 ); + testcase( jumpIfNull==0 ); break; } } @@ -48881,15 +50934,25 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList) ** Allocate or deallocate temporary use registers during code generation. */ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){ - if( pParse->nTempReg ){ - return pParse->aTempReg[--pParse->nTempReg]; - }else{ + int i, r; + if( pParse->nTempReg==0 ){ + return ++pParse->nMem; + } + for(i=0; inTempReg; i++){ + r = pParse->aTempReg[i]; + if( usedAsColumnCache(pParse, r, r) ) continue; + } + if( i>=pParse->nTempReg ){ return ++pParse->nMem; } + while( inTempReg-1 ){ + pParse->aTempReg[i] = pParse->aTempReg[i+1]; + } + pParse->nTempReg--; + return r; } SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempRegaTempReg) ){ - assert( iReg>0 ); pParse->aTempReg[pParse->nTempReg++] = iReg; } } @@ -48898,9 +50961,10 @@ SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ ** Allocate or deallocate a block of nReg consecutive registers */ SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){ - int i; - if( nReg<=pParse->nRangeReg ){ - i = pParse->iRangeReg; + int i, n; + i = pParse->iRangeReg; + n = pParse->nRangeReg; + if( nReg<=n && !usedAsColumnCache(pParse, i, i+n-1) ){ pParse->iRangeReg += nReg; pParse->nRangeReg -= nReg; }else{ @@ -48932,7 +50996,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.42 2008/02/09 14:30:30 drh Exp $ +** $Id: alter.c,v 1.44 2008/05/09 14:17:52 drh Exp $ */ /* @@ -48969,11 +51033,11 @@ static void renameTableFunc( int len = 0; char *zRet; - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); /* The principle used to locate the table name in the CREATE TABLE - ** statement is that the table name is the first token that is immediatedly - ** followed by a left parenthesis - TK_LP - or "USING" TK_USING. + ** statement is that the table name is the first non-space token that + ** is immediately followed by a left parenthesis - TK_LP - or "USING" TK_USING. */ if( zSql ){ do { @@ -48992,7 +51056,7 @@ static void renameTableFunc( do { zCsr += len; len = sqlite3GetToken(zCsr, &token); - } while( token==TK_SPACE ); + } while( token==TK_SPACE || token==TK_COMMENT ); assert( len>0 ); } while( token!=TK_LP && token!=TK_USING ); @@ -49025,7 +51089,7 @@ static void renameTriggerFunc( int len = 0; char *zRet; - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); /* The principle used to locate the table name in the CREATE TRIGGER ** statement is that the table name is the first token that is immediatedly @@ -49096,7 +51160,7 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(sqlite3 *db){ for(i=0; idb, pIdx->pSchema) ); + nCol = pIdx->nColumn; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nCol+1); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); - nCol = pIdx->nColumn; regFields = iMem+nCol*2; regTemp = regRowid = regCol = regFields+3; regRec = regCol+1; if( regRec>pParse->nMem ){ pParse->nMem = regRec; } - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, nCol+1); /* Memory cells are used as follows: ** @@ -49989,7 +52053,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.72 2008/02/13 18:25:27 danielk1977 Exp $ +** $Id: attach.c,v 1.75 2008/04/17 17:02:01 drh Exp $ */ #ifndef SQLITE_OMIT_ATTACH @@ -50046,7 +52110,7 @@ static void attachFunc( ){ int i; int rc = 0; - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); const char *zName; const char *zFile; Db *aNew; @@ -50064,10 +52128,10 @@ static void attachFunc( ** * Transaction currently open ** * Specified database name already being used. */ - if( db->nDb>=SQLITE_MAX_ATTACHED+2 ){ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ sqlite3_snprintf( sizeof(zErr), zErr, "too many attached databases - max %d", - SQLITE_MAX_ATTACHED + db->aLimit[SQLITE_LIMIT_ATTACHED] ); goto attach_error; } @@ -50114,6 +52178,7 @@ static void attachFunc( db->openFlags | SQLITE_OPEN_MAIN_DB, &aNew->pBt); if( rc==SQLITE_OK ){ + Pager *pPager; aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); if( !aNew->pSchema ){ rc = SQLITE_NOMEM; @@ -50122,7 +52187,9 @@ static void attachFunc( "attached databases must use the same text encoding as main database"); goto attach_error; } - sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode); + pPager = sqlite3BtreePager(aNew->pBt); + sqlite3PagerLockingMode(pPager, db->dfltLockMode); + sqlite3PagerJournalMode(pPager, db->dfltJournalMode); } aNew->zName = sqlite3DbStrDup(db, zName); aNew->safety_level = 3; @@ -50216,7 +52283,7 @@ static void detachFunc( sqlite3_value **argv ){ const char *zName = (const char *)sqlite3_value_text(argv[0]); - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); int i; Db *pDb = 0; char zErr[128]; @@ -50355,8 +52422,8 @@ SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *p SQLITE_PRIVATE void sqlite3AttachFunctions(sqlite3 *db){ #ifndef SQLITE_OMIT_ATTACH static const int enc = SQLITE_UTF8; - sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0); - sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0); + sqlite3CreateFunc(db, "sqlite_attach", 3, enc, 0, attachFunc, 0, 0); + sqlite3CreateFunc(db, "sqlite_detach", 1, enc, 0, detachFunc, 0, 0); #endif } @@ -50765,7 +52832,7 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.474 2008/03/06 09:58:50 mlcreech Exp $ +** $Id: build.c,v 1.484 2008/05/01 17:16:53 drh Exp $ */ /* @@ -50852,10 +52919,8 @@ static void codeTableLocks(Parse *pParse){ for(i=0; inTableLock; i++){ TableLock *p = &pParse->aTableLock[i]; int p1 = p->iDb; - if( p->isWriteLock ){ - p1 = -1*(p1+1); - } - sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, 0, p->zName, P4_STATIC); + sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock, + p->zName, P4_STATIC); } } #else @@ -50911,9 +52976,13 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } #ifndef SQLITE_OMIT_VIRTUALTABLE - if( pParse->pVirtualLock ){ - char *vtab = (char *)pParse->pVirtualLock->pVtab; - sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); + { + int i; + for(i=0; inVtabLock; i++){ + char *vtab = (char *)pParse->apVtabLock[i]->pVtab; + sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); + } + pParse->nVtabLock = 0; } #endif @@ -50946,6 +53015,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); #endif + assert( pParse->disableColCache==0 ); /* Disables and re-enables match */ sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, pParse->nTab+3, pParse->explain); pParse->rc = SQLITE_DONE; @@ -51349,8 +53419,8 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ Vdbe *v = sqlite3GetVdbe(p); sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5);/* sqlite_master has 5 columns */ sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ } /* @@ -51674,11 +53744,14 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){ int i; char *z; Column *pCol; + sqlite3 *db = pParse->db; if( (p = pParse->pNewTable)==0 ) return; - if( p->nCol+1>SQLITE_MAX_COLUMN ){ +#if SQLITE_MAX_COLUMN + if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); return; } +#endif z = sqlite3NameFromToken(pParse->db, pName); if( z==0 ) return; for(i=0; inCol; i++){ @@ -52811,6 +54884,14 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); + + /* Drop any statistics from the sqlite_stat1 table, if it exists */ + if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb->zName, pTab->zName + ); + } + if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } @@ -53016,7 +55097,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); regRecord = sqlite3GetTempReg(pParse); - regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord); + regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); if( pIndex->onError!=OE_None ){ int j1, j2; int regRowid; @@ -53024,7 +55105,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ regRowid = regIdxKey + pIndex->nColumn; j1 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdxKey, 0, pIndex->nColumn); j2 = sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, - 0, regRowid, (char*)(sqlite3_intptr_t)regRecord, P4_INT32); + 0, regRowid, (char*)regRecord, P4_INT32); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0, "indexed columns are not unique", P4_STATIC); sqlite3VdbeJumpHere(v, j1); @@ -53596,6 +55677,12 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName ); + if( sqlite3FindTable(db, "sqlite_stat1", db->aDb[iDb].zName) ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q", + db->aDb[iDb].zName, pIndex->zName + ); + } sqlite3ChangeCookie(pParse, iDb); destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); @@ -53960,6 +56047,8 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){ } assert( (db->flags & SQLITE_InTrans)==0 || db->autoCommit ); assert( db->aDb[1].pSchema ); + sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt), + db->dfltJournalMode); } return 0; } @@ -54603,7 +56692,7 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.161 2008/02/12 16:52:14 drh Exp $ +** $Id: delete.c,v 1.169 2008/04/28 18:46:43 drh Exp $ */ /* @@ -54665,9 +56754,9 @@ SQLITE_PRIVATE void sqlite3OpenTable( v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); VdbeComment((v, "%s", pTab->zName)); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iCur, pTab->nCol); } @@ -54681,7 +56770,6 @@ SQLITE_PRIVATE void sqlite3MaterializeView( Parse *pParse, /* Parsing context */ Select *pView, /* View definition */ Expr *pWhere, /* Optional WHERE clause to be added */ - u32 col_mask, /* Render only the columns in this mask. */ int iCur /* Cursor number for ephemerial table */ ){ SelectDest dest; @@ -54696,7 +56784,6 @@ SQLITE_PRIVATE void sqlite3MaterializeView( pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0); pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); } - sqlite3SelectMask(pParse, pDup, col_mask); sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest, 0, 0, 0, 0); sqlite3SelectDelete(pDup); @@ -54838,7 +56925,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** a ephemeral table. */ if( isView ){ - sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, old_col_mask, iCur); + sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur); } /* Resolve the column names in the WHERE clause. @@ -54912,8 +56999,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( /* Open the pseudo-table used to store OLD if there are triggers. */ if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol); } /* Delete every item whose key was written to the list during the @@ -54963,7 +57050,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ const char *pVtab = (const char *)pTab->pVtab; - pParse->pVirtualLock = pTab; + sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB); }else #endif @@ -55078,18 +57165,16 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete( Index *pIdx; int r1; - r1 = sqlite3GetTempReg(pParse); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; - sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1); - sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1); + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0); + sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1); } - sqlite3ReleaseTempReg(pParse, r1); } /* -** Generate code that will assemble an index key and put it on the top -** of the tack. The key with be for index pIdx which is an index on pTab. +** Generate code that will assemble an index key and put it in register +** regOut. The key with be for index pIdx which is an index on pTab. ** iCur is the index of a cursor open on the pTab table and pointing to ** the entry that needs indexing. ** @@ -55102,7 +57187,8 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( Parse *pParse, /* Parsing context */ Index *pIdx, /* The index for which to generate a key */ int iCur, /* Cursor number for the pIdx->pTable table */ - int regOut /* Write the new index key to this register */ + int regOut, /* Write the new index key to this register */ + int doMakeRec /* Run the OP_MakeRecord instruction if true */ ){ Vdbe *v = pParse->pVdbe; int j; @@ -55122,12 +57208,20 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( sqlite3ColumnDefault(v, pTab, idx); } } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); - sqlite3IndexAffinityStr(v, pIdx); + if( doMakeRec ){ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1); + } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } +/* Make sure "isView" gets undefined in case this file becomes part of +** the amalgamation - so that subsequent files do not see isView as a +** macro. */ +#undef isView + /************** End of delete.c **********************************************/ /************** Begin file func.c ********************************************/ /* @@ -55148,7 +57242,7 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.186 2008/03/06 09:58:50 mlcreech Exp $ +** $Id: func.c,v 1.192 2008/04/27 18:40:12 drh Exp $ */ @@ -55315,7 +57409,7 @@ static void substrFunc( if( argc==3 ){ p2 = sqlite3_value_int(argv[2]); }else{ - p2 = SQLITE_MAX_LENGTH; + p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH]; } if( p1<0 ){ p1 += len; @@ -55370,10 +57464,16 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ ** allocation fails, call sqlite3_result_error_nomem() to notify ** the database handle that malloc() has failed. */ -static void *contextMalloc(sqlite3_context *context, int nByte){ - char *z = sqlite3_malloc(nByte); - if( !z && nByte>0 ){ - sqlite3_result_error_nomem(context); +static void *contextMalloc(sqlite3_context *context, i64 nByte){ + char *z; + if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + z = 0; + }else{ + z = sqlite3_malloc(nByte); + if( !z && nByte>0 ){ + sqlite3_result_error_nomem(context); + } } return z; } @@ -55391,7 +57491,7 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ /* Verify that the call to _bytes() does not invalidate the _text() pointer */ assert( z2==(char*)sqlite3_value_text(argv[0]) ); if( z2 ){ - z1 = contextMalloc(context, n+1); + z1 = contextMalloc(context, ((i64)n)+1); if( z1 ){ memcpy(z1, z2, n+1); for(i=0; z1[i]; i++){ @@ -55411,7 +57511,7 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ /* Verify that the call to _bytes() does not invalidate the _text() pointer */ assert( z2==(char*)sqlite3_value_text(argv[0]) ); if( z2 ){ - z1 = contextMalloc(context, n+1); + z1 = contextMalloc(context, ((i64)n)+1); if( z1 ){ memcpy(z1, z2, n+1); for(i=0; z1[i]; i++){ @@ -55450,7 +57550,7 @@ static void randomFunc( sqlite3_value **argv ){ sqlite_int64 r; - sqlite3Randomness(sizeof(r), &r); + sqlite3_randomness(sizeof(r), &r); if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */ /* can always do abs() of the result */ sqlite3_result_int64(context, r); @@ -55472,13 +57572,9 @@ static void randomBlob( if( n<1 ){ n = 1; } - if( n>SQLITE_MAX_LENGTH ){ - sqlite3_result_error_toobig(context); - return; - } p = contextMalloc(context, n); if( p ){ - sqlite3Randomness(n, p); + sqlite3_randomness(n, p); sqlite3_result_blob(context, (char*)p, n, sqlite3_free); } } @@ -55492,7 +57588,7 @@ static void last_insert_rowid( int arg, sqlite3_value **argv ){ - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); } @@ -55505,7 +57601,7 @@ static void changes( int arg, sqlite3_value **argv ){ - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); sqlite3_result_int(context, sqlite3_changes(db)); } @@ -55518,7 +57614,7 @@ static void total_changes( int arg, sqlite3_value **argv ){ - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); sqlite3_result_int(context, sqlite3_total_changes(db)); } @@ -55718,6 +57814,7 @@ static void likeFunc( ){ const unsigned char *zA, *zB; int escape = 0; + sqlite3 *db = sqlite3_context_db_handle(context); zB = sqlite3_value_text(argv[0]); zA = sqlite3_value_text(argv[1]); @@ -55725,7 +57822,8 @@ static void likeFunc( /* Limit the length of the LIKE or GLOB pattern to avoid problems ** of deep recursion and N*N behavior in patternCompare(). */ - if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ + if( sqlite3_value_bytes(argv[0]) > + db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); return; } @@ -55817,12 +57915,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char const *zBlob = sqlite3_value_blob(argv[0]); int nBlob = sqlite3_value_bytes(argv[0]); assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - - if( 2*nBlob+4>SQLITE_MAX_LENGTH ){ - sqlite3_result_error_toobig(context); - return; - } - zText = (char *)contextMalloc(context, (2*nBlob)+4); + zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); if( zText ){ int i; for(i=0; iSQLITE_MAX_LENGTH ){ - sqlite3_result_error_toobig(context); - return; - } - z = contextMalloc(context, i+n+3); + z = contextMalloc(context, ((i64)i)+((i64)n)+3); if( z ){ z[0] = '\''; for(i=0, j=1; zArg[i]; i++){ @@ -55882,12 +57971,8 @@ static void hexFunc( assert( argc==1 ); pBlob = sqlite3_value_blob(argv[0]); n = sqlite3_value_bytes(argv[0]); - if( n*2+1>SQLITE_MAX_LENGTH ){ - sqlite3_result_error_toobig(context); - return; - } assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - z = zHex = contextMalloc(context, n*2 + 1); + z = zHex = contextMalloc(context, ((i64)n)*2 + 1); if( zHex ){ for(i=0; i=SQLITE_MAX_LENGTH ){ + if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); sqlite3_free(zOut); return; @@ -56002,7 +58088,7 @@ static void trimFunc( const unsigned char *zIn; /* Input string */ const unsigned char *zCharSet; /* Set of characters to trim */ int nIn; /* Number of bytes in input */ - sqlite3_intptr_t flags; /* 1: trimleft 2: trimright 3: trim */ + int flags; /* 1: trimleft 2: trimright 3: trim */ int i; /* Loop counter */ unsigned char *aLen; /* Length of each character in zCharSet */ unsigned char **azChar; /* Individual characters in zCharSet */ @@ -56030,7 +58116,7 @@ static void trimFunc( SQLITE_SKIP_UTF8(z); } if( nChar>0 ){ - azChar = contextMalloc(context, nChar*(sizeof(char*)+1)); + azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1)); if( azChar==0 ){ return; } @@ -56043,7 +58129,7 @@ static void trimFunc( } } if( nChar>0 ){ - flags = (sqlite3_intptr_t)sqlite3_user_data(context); + flags = (int)sqlite3_user_data(context); if( flags & 1 ){ while( nIn>0 ){ int len; @@ -56132,7 +58218,7 @@ static void soundexFunc( static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *zFile = (const char *)sqlite3_value_text(argv[0]); const char *zProc; - sqlite3 *db = sqlite3_user_data(context); + sqlite3 *db = sqlite3_context_db_handle(context); char *zErrMsg = 0; if( argc==2 ){ @@ -56147,166 +58233,6 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ } #endif -#ifdef SQLITE_TEST -/* -** This function generates a string of random characters. Used for -** generating test data. -*/ -static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ - static const unsigned char zSrc[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789" - ".-!,:*^+=_|?/<> "; - int iMin, iMax, n, r, i; - unsigned char zBuf[1000]; - - /* It used to be possible to call randstr() with any number of arguments, - ** but now it is registered with SQLite as requiring exactly 2. - */ - assert(argc==2); - - iMin = sqlite3_value_int(argv[0]); - if( iMin<0 ) iMin = 0; - if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; - iMax = sqlite3_value_int(argv[1]); - if( iMax=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; - n = iMin; - if( iMax>iMin ){ - sqlite3Randomness(sizeof(r), &r); - r &= 0x7fffffff; - n += r%(iMax + 1 - iMin); - } - assert( nuseMalloc = 1; + pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; if( pAccum->nChar ){ if( argc==2 ){ zSep = (char*)sqlite3_value_text(argv[1]); @@ -56506,7 +58434,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ static const struct { char *zName; signed char nArg; - u8 argType; /* ff: db 1: 0, 2: 1, 3: 2,... N: N-1. */ + u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */ u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ u8 needCollSeq; void (*xFunc)(sqlite3_context*,int,sqlite3_value **); @@ -56534,9 +58462,9 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, - { "last_insert_rowid", 0, 0xff, SQLITE_UTF8, 0, last_insert_rowid }, - { "changes", 0, 0xff, SQLITE_UTF8, 0, changes }, - { "total_changes", 0, 0xff, SQLITE_UTF8, 0, total_changes }, + { "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid }, + { "changes", 0, 0, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes }, { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc }, { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc }, @@ -56549,15 +58477,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION - { "load_extension", 1, 0xff, SQLITE_UTF8, 0, loadExt }, - { "load_extension", 2, 0xff, SQLITE_UTF8, 0, loadExt }, -#endif -#ifdef SQLITE_TEST - { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, - { "test_destructor", 1, 0xff, SQLITE_UTF8, 0, test_destructor}, - { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, - { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, - { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, + { "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt }, #endif }; static const struct { @@ -56583,11 +58504,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ for(i=0; ipTable; sqlite3 *db = sqlite3VdbeDb(v); - pIdx->zColAff = (char *)sqlite3DbMallocZero(db, pIdx->nColumn+2); + pIdx->zColAff = (char *)sqlite3DbMallocRaw(db, pIdx->nColumn+2); if( !pIdx->zColAff ){ return; } @@ -56788,7 +58705,7 @@ SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ int i; sqlite3 *db = sqlite3VdbeDb(v); - zColAff = (char *)sqlite3DbMallocZero(db, pTab->nCol+1); + zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1); if( !zColAff ){ return; } @@ -57239,8 +59156,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** back up and execute the SELECT code above. */ sqlite3VdbeJumpHere(v, iInitCode); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, srcTab, nColumn); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iCleanup); }else{ @@ -57331,8 +59247,8 @@ SQLITE_PRIVATE void sqlite3Insert( /* Open the temp table for FOR EACH ROW triggers */ if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted @@ -57349,7 +59265,7 @@ SQLITE_PRIVATE void sqlite3Insert( baseCur = pParse->nTab; nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite); - aRegIdx = sqlite3DbMallocZero(db, sizeof(int)*(nIdx+1)); + aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1)); if( aRegIdx==0 ){ goto insert_cleanup; } @@ -57549,7 +59465,7 @@ SQLITE_PRIVATE void sqlite3Insert( */ #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) ){ - pParse->pVirtualLock = pTab; + sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, (const char*)pTab->pVtab, P4_VTAB); }else @@ -57874,6 +59790,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); sqlite3IndexAffinityStr(v, pIdx); + sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1); sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); /* Find out what action to take in case there is an indexing conflict */ @@ -57895,7 +59812,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( regR = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR); j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, - regR, (char*)(sqlite3_intptr_t)aRegIdx[iCur], + regR, (char*)aRegIdx[iCur], P4_INT32); /* Generate code that executes if the new index entry is not unique */ @@ -57988,6 +59905,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3TableAffinityStr(v, pTab); + sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol); #ifndef SQLITE_OMIT_TRIGGER if( newIdx>=0 ){ sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); @@ -58366,6 +60284,11 @@ static int xferOptimization( } #endif /* SQLITE_OMIT_XFER_OPT */ +/* Make sure "isView" gets undefined in case this file becomes part of +** the amalgamation - so that subsequent files do not see isView as a +** macro. */ +#undef isView + /************** End of insert.c **********************************************/ /************** Begin file legacy.c ******************************************/ /* @@ -58384,7 +60307,7 @@ static int xferOptimization( ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.23 2008/02/13 18:25:27 danielk1977 Exp $ +** $Id: legacy.c,v 1.24 2008/03/21 18:01:14 drh Exp $ */ @@ -58433,12 +60356,7 @@ SQLITE_API int sqlite3_exec( } nCallback = 0; - nCol = sqlite3_column_count(pStmt); - azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char *) + 1); - if( azCols==0 ){ - goto exec_out; - } while( 1 ){ int i; @@ -58448,6 +60366,12 @@ SQLITE_API int sqlite3_exec( if( xCallback && (SQLITE_ROW==rc || (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){ if( 0==nCallback ){ + if( azCols==0 ){ + azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1); + if( azCols==0 ){ + goto exec_out; + } + } for(i=0; ivfs_find #define sqlite3_vfs_register sqlite3_api->vfs_register #define sqlite3_vfs_unregister sqlite3_api->vfs_unregister +#define sqlite3_threadsafe sqlite3_api->xthreadsafe +#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob +#define sqlite3_result_error_code sqlite3_api->result_error_code +#define sqlite3_test_control sqlite3_api->test_control +#define sqlite3_randomness sqlite3_api->randomness +#define sqlite3_context_db_handle sqlite3_api->context_db_handle #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; @@ -58885,6 +60820,8 @@ struct sqlite3_api_routines { /************** End of sqlite3ext.h ******************************************/ /************** Continuing where we left off in loadext.c ********************/ +#ifndef SQLITE_OMIT_LOAD_EXTENSION + /* ** Some API routines are omitted when various features are ** excluded from a build of SQLite. Substitute a NULL pointer @@ -58982,7 +60919,7 @@ struct sqlite3_api_routines { ** also check to make sure that the pointer to the function is ** not NULL before calling it. */ -SQLITE_PRIVATE const sqlite3_api_routines sqlite3Apis = { +static const sqlite3_api_routines sqlite3Apis = { sqlite3_aggregate_context, sqlite3_aggregate_count, sqlite3_bind_blob, @@ -59155,6 +61092,16 @@ SQLITE_PRIVATE const sqlite3_api_routines sqlite3Apis = { sqlite3_vfs_find, sqlite3_vfs_register, sqlite3_vfs_unregister, + + /* + ** Added for 3.5.8 + */ + sqlite3_threadsafe, + sqlite3_result_zeroblob, + sqlite3_result_error_code, + sqlite3_test_control, + sqlite3_randomness, + sqlite3_context_db_handle, }; /* @@ -59288,6 +61235,19 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ return SQLITE_OK; } +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ + +/* +** The auto-extension code added regardless of whether or not extension +** loading is supported. We need a dummy sqlite3Apis pointer for that +** code if regular extension loading is not available. This is that +** dummy pointer. +*/ +#ifdef SQLITE_OMIT_LOAD_EXTENSION +static const sqlite3_api_routines sqlite3Apis = { 0 }; +#endif + + /* ** The following object holds the list of automatically loaded ** extensions. @@ -59308,7 +61268,9 @@ static struct { SQLITE_API int sqlite3_auto_extension(void *xInit){ int i; int rc = SQLITE_OK; +#ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); +#endif sqlite3_mutex_enter(mutex); for(i=0; i=autoext.nExt ){ xInit = 0; @@ -59378,8 +61344,6 @@ SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){ return rc; } -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ - /************** End of loadext.c *********************************************/ /************** Begin file pragma.c ******************************************/ /* @@ -59395,7 +61359,7 @@ SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.170 2008/02/13 18:25:27 danielk1977 Exp $ +** $Id: pragma.c,v 1.176 2008/04/17 20:59:38 drh Exp $ */ /* Ignore this whole file if pragmas are disabled @@ -59732,7 +61696,8 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Malloc may fail when setting the page-size, as there is an internal ** buffer that the pager module resizes using sqlite3_realloc(). */ - if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1) ){ + db->nextPagesize = atoi(zRight); + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1) ){ db->mallocFailed = 1; } } @@ -59805,6 +61770,63 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); }else + + /* + ** PRAGMA [database.]journal_mode + ** PRAGMA [database.]journal_mode = (delete|persist|off) + */ + if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){ + int eMode; + static const char *azModeName[] = {"delete", "persist", "off"}; + + if( zRight==0 ){ + eMode = PAGER_JOURNALMODE_QUERY; + }else{ + int n = strlen(zRight); + eMode = 2; + while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){ + eMode--; + } + } + if( pId2->n==0 && eMode==PAGER_JOURNALMODE_QUERY ){ + /* Simple "PRAGMA persistent_journal;" statement. This is a query for + ** the current default journal mode (which may be different to + ** the journal-mode of the main database). + */ + eMode = db->dfltJournalMode; + }else{ + Pager *pPager; + if( pId2->n==0 ){ + /* This indicates that no database name was specified as part + ** of the PRAGMA command. In this case the journal-mode must be + ** set on all attached databases, as well as the main db file. + ** + ** Also, the sqlite3.dfltJournalMode variable is set so that + ** any subsequently attached databases also use the specified + ** journal mode. + */ + int ii; + assert(pDb==&db->aDb[0]); + for(ii=1; iinDb; ii++){ + if( db->aDb[ii].pBt ){ + pPager = sqlite3BtreePager(db->aDb[ii].pBt); + sqlite3PagerJournalMode(pPager, eMode); + } + } + db->dfltJournalMode = eMode; + } + pPager = sqlite3BtreePager(pDb->pBt); + eMode = sqlite3PagerJournalMode(pPager, eMode); + } + assert( eMode==PAGER_JOURNALMODE_DELETE + || eMode==PAGER_JOURNALMODE_PERSIST + || eMode==PAGER_JOURNALMODE_OFF ); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, + azModeName[eMode], P4_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ /* @@ -59952,7 +61974,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } }else{ if( zRight[0] - && !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE) + && sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE)==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); goto pragma_out; @@ -60319,13 +62341,16 @@ SQLITE_PRIVATE void sqlite3Pragma( { OP_Concat, 5, 3, 3}, { OP_Concat, 6, 3, 3}, { OP_ResultRow, 3, 1, 0}, + { OP_IfPos, 1, 0, 0}, /* 9 */ + { OP_Halt, 0, 0, 0}, }; - sqlite3GenerateIndexKey(pParse, pIdx, 1, 3); + sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1); jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3); addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC); sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC); sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_STATIC); + sqlite3VdbeJumpHere(v, addr+9); sqlite3VdbeJumpHere(v, jmp2); } sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1); @@ -60626,16 +62651,21 @@ pragma_out: ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.78 2008/03/08 12:23:31 drh Exp $ +** $Id: prepare.c,v 1.83 2008/04/03 14:36:26 danielk1977 Exp $ */ /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ -static void corruptSchema(InitData *pData, const char *zExtra){ +static void corruptSchema( + InitData *pData, /* Initialization context */ + const char *zObj, /* Object being parsed at the point of error */ + const char *zExtra /* Error information */ +){ if( !pData->db->mallocFailed ){ - sqlite3SetString(pData->pzErrMsg, "malformed database schema", + if( zObj==0 ) zObj = "?"; + sqlite3SetString(pData->pzErrMsg, "malformed database schema (", zObj, ")", zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); } pData->rc = SQLITE_CORRUPT; @@ -60662,14 +62692,14 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char pData->rc = SQLITE_OK; DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ - corruptSchema(pData, 0); + corruptSchema(pData, argv[0], 0); return SQLITE_NOMEM; } assert( argc==3 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ - corruptSchema(pData, 0); + corruptSchema(pData, argv[0], 0); return 1; } assert( iDb>=0 && iDbnDb ); @@ -60692,13 +62722,13 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char if( rc==SQLITE_NOMEM ){ db->mallocFailed = 1; }else if( rc!=SQLITE_INTERRUPT ){ - corruptSchema(pData, zErr); + corruptSchema(pData, argv[0], zErr); } sqlite3_free(zErr); return 1; } }else if( argv[0]==0 ){ - corruptSchema(pData, 0); + corruptSchema(pData, 0, 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE @@ -60813,12 +62843,16 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } return SQLITE_OK; } + curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); + if( !curMain ){ + rc = SQLITE_NOMEM; + goto error_out; + } sqlite3BtreeEnter(pDb->pBt); - rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); - sqlite3BtreeLeave(pDb->pBt); - goto error_out; + goto leave_error_out; } /* Get the database meta information. @@ -60845,9 +62879,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } if( rc ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); - sqlite3BtreeCloseCursor(curMain); - sqlite3BtreeLeave(pDb->pBt); - goto error_out; + goto leave_error_out; } }else{ memset(meta, 0, sizeof(meta)); @@ -60867,11 +62899,10 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ }else{ /* If opening an attached database, the encoding much match ENC(db) */ if( meta[4]!=ENC(db) ){ - sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "attached databases must use the same" " text encoding as main database", (char*)0); - sqlite3BtreeLeave(pDb->pBt); - return SQLITE_ERROR; + rc = SQLITE_ERROR; + goto leave_error_out; } } }else{ @@ -60896,10 +62927,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ pDb->pSchema->file_format = 1; } if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ - sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); - sqlite3BtreeLeave(pDb->pBt); - return SQLITE_ERROR; + rc = SQLITE_ERROR; + goto leave_error_out; } /* Ticket #2804: When we open a database in the newer file format, @@ -60942,7 +62972,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ sqlite3AnalysisLoad(db, iDb); } #endif - sqlite3BtreeCloseCursor(curMain); } if( db->mallocFailed ){ /* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */ @@ -60961,6 +62990,14 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ DbSetProperty(db, iDb, DB_SchemaLoaded); rc = SQLITE_OK; } + + /* Jump here for an error that occurs after successfully allocating + ** curMain and calling sqlite3BtreeEnter(). For an error that occurs + ** before that point, jump to error_out. + */ +leave_error_out: + sqlite3BtreeCloseCursor(curMain); + sqlite3_free(curMain); sqlite3BtreeLeave(pDb->pBt); error_out: @@ -61047,23 +63084,32 @@ static int schemaIsValid(sqlite3 *db){ int cookie; int allOk = 1; - assert( sqlite3_mutex_held(db->mutex) ); - for(iDb=0; allOk && iDbnDb; iDb++){ - Btree *pBt; - pBt = db->aDb[iDb].pBt; - if( pBt==0 ) continue; - rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); - if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - allOk = 0; + curTemp = (BtCursor *)sqlite3_malloc(sqlite3BtreeCursorSize()); + if( curTemp ){ + assert( sqlite3_mutex_held(db->mutex) ); + for(iDb=0; allOk && iDbnDb; iDb++){ + Btree *pBt; + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) continue; + memset(curTemp, 0, sqlite3BtreeCursorSize()); + rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); + if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ + allOk = 0; + } + sqlite3BtreeCloseCursor(curTemp); + } + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; } - sqlite3BtreeCloseCursor(curTemp); - } - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; } + sqlite3_free(curTemp); + }else{ + allOk = 0; + db->mallocFailed = 1; } + return allOk; } @@ -61142,9 +63188,10 @@ static int sqlite3Prepare( memset(&sParse, 0, sizeof(sParse)); sParse.db = db; - if( nBytes>=0 && zSql[nBytes]!=0 ){ + if( nBytes>=0 && zSql[nBytes-1]!=0 ){ char *zSqlCopy; - if( SQLITE_MAX_SQL_LENGTH>0 && nBytes>SQLITE_MAX_SQL_LENGTH ){ + int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; + if( nBytes>mxLen ){ sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); (void)sqlite3SafetyOff(db); return SQLITE_TOOBIG; @@ -61153,8 +63200,10 @@ static int sqlite3Prepare( if( zSqlCopy ){ sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); sqlite3_free(zSqlCopy); + sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; + }else{ + sParse.zTail = &zSql[nBytes]; } - sParse.zTail = &zSql[nBytes]; }else{ sqlite3RunParser(&sParse, zSql, &zErrMsg); } @@ -61406,7 +63455,7 @@ SQLITE_API int sqlite3_prepare16_v2( ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.415 2008/03/04 17:45:01 mlcreech Exp $ +** $Id: select.c,v 1.429 2008/05/01 17:03:49 drh Exp $ */ @@ -61434,6 +63483,7 @@ SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iPar pDest->iParm = iParm; pDest->affinity = 0; pDest->iMem = 0; + pDest->nMem = 0; } @@ -61597,12 +63647,30 @@ static void setToken(Token *p, const char *z){ ** {a"bc} -> {"a""bc"} */ static void setQuotedToken(Parse *pParse, Token *p, const char *z){ - p->z = (u8 *)sqlite3MPrintf(0, "\"%w\"", z); - p->dyn = 1; - if( p->z ){ - p->n = strlen((char *)p->z); + + /* Check if the string contains any " characters. If it does, then + ** this function will malloc space to create a quoted version of + ** the string in. Otherwise, save a call to sqlite3MPrintf() by + ** just copying the pointer to the string. + */ + const char *z2 = z; + while( *z2 ){ + if( *z2=='"' ) break; + z2++; + } + + if( *z2 ){ + /* String contains " characters - copy and quote the string. */ + p->z = (u8 *)sqlite3MPrintf(pParse->db, "\"%w\"", z); + if( p->z ){ + p->n = strlen((char *)p->z); + p->dyn = 1; + } }else{ - pParse->db->mallocFailed = 1; + /* String contains no " characters - copy the pointer. */ + p->z = (u8*)z; + p->n = (z2 - z); + p->dyn = 0; } } @@ -61615,7 +63683,6 @@ SQLITE_PRIVATE Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); } - /* ** Add a term to the WHERE expression in *ppExpr that requires the ** zCol column to be equal in the two tables pTab1 and pTab2. @@ -61628,7 +63695,8 @@ static void addWhereTerm( const Table *pTab2, /* Second table */ const char *zAlias2, /* Alias for second table. May be NULL */ int iRightJoinTable, /* VDBE cursor for the right table */ - Expr **ppExpr /* Add the equality term to this expression */ + Expr **ppExpr, /* Add the equality term to this expression */ + int isOuterJoin /* True if dealing with an OUTER join */ ){ Expr *pE1a, *pE1b, *pE1c; Expr *pE2a, *pE2b, *pE2c; @@ -61647,7 +63715,7 @@ static void addWhereTerm( pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0); pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0); pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0); - if( pE ){ + if( pE && isOuterJoin ){ ExprSetProperty(pE, EP_FromJoin); pE->iRightJoinTable = iRightJoinTable; } @@ -61715,8 +63783,10 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ for(i=0; inSrc-1; i++, pRight++, pLeft++){ Table *pLeftTab = pLeft->pTab; Table *pRightTab = pRight->pTab; + int isOuter; if( pLeftTab==0 || pRightTab==0 ) continue; + isOuter = (pRight->jointype & JT_OUTER)!=0; /* When the NATURAL keyword is present, add WHERE clause terms for ** every column that the two tables have in common. @@ -61732,7 +63802,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ if( columnIndex(pRightTab, zName)>=0 ){ addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, pRightTab, pRight->zAlias, - pRight->iCursor, &p->pWhere); + pRight->iCursor, &p->pWhere, isOuter); } } @@ -61750,7 +63820,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ ** an AND operator. */ if( pRight->pOn ){ - setJoinExpr(pRight->pOn, pRight->iCursor); + if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor); p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn); pRight->pOn = 0; } @@ -61773,7 +63843,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ } addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, pRightTab, pRight->zAlias, - pRight->iCursor, &p->pWhere); + pRight->iCursor, &p->pWhere, isOuter); } } } @@ -61794,9 +63864,9 @@ static void pushOntoSorter( int nExpr = pOrderBy->nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr+2); int regRecord = sqlite3GetTempReg(pParse); - sqlite3ExprCodeExprList(pParse, pOrderBy, regBase); + sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); - sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1); + sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); @@ -61936,6 +64006,12 @@ static void selectInnerLoop( } if( pDest->iMem==0 ){ pDest->iMem = sqlite3GetTempRange(pParse, nResultCol); + pDest->nMem = nResultCol; + }else if( pDest->nMem!=nResultCol ){ + /* This happens when two SELECTs of a compound SELECT have differing + ** numbers of result columns. The error message will be generated by + ** a higher-level routine. */ + return; } regResult = pDest->iMem; if( nColumn>0 ){ @@ -61946,9 +64022,7 @@ static void selectInnerLoop( /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ - for(i=0; ia[i].pExpr, regResult+i); - } + sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback); } nColumn = nResultCol; @@ -61991,12 +64065,7 @@ static void selectInnerLoop( ** the temporary table iParm. */ case SRT_Except: { - int r1; - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); - sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); - sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1); - sqlite3ReleaseTempReg(pParse, r1); + sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn); break; } #endif @@ -62040,6 +64109,7 @@ static void selectInnerLoop( }else{ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, regResult, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); } @@ -62064,7 +64134,7 @@ static void selectInnerLoop( if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p, regResult); }else{ - sqlite3VdbeAddOp2(v, OP_Move, regResult, iParm); + sqlite3ExprCodeMove(pParse, regResult, iParm); /* The LIMIT clause will jump out of the loop for us */ } break; @@ -62086,6 +64156,7 @@ static void selectInnerLoop( sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); + sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); } break; } @@ -62182,8 +64253,8 @@ static void generateSortTail( iTab = pOrderBy->iECursor; if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ pseudoTab = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn); + sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback); } addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); codeOffset(v, p, cont); @@ -62204,13 +64275,14 @@ static void generateSortTail( assert( nColumn==1 ); j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); + sqlite3ExprCacheAffinityChange(pParse, regRow, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); sqlite3VdbeJumpHere(v, j1); break; } case SRT_Mem: { assert( nColumn==1 ); - sqlite3VdbeAddOp2(v, OP_Move, regRow, iParm); + sqlite3ExprCodeMove(pParse, regRow, iParm); /* The LIMIT clause will terminate the loop for us */ break; } @@ -62221,10 +64293,12 @@ static void generateSortTail( sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); for(i=0; iiMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); } if( eDest==SRT_Callback ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); + sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); }else{ sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); } @@ -62398,6 +64472,7 @@ static void generateColumnTypes( SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ +#ifndef SQLITE_OMIT_DECLTYPE Vdbe *v = pParse->pVdbe; int i; NameContext sNC; @@ -62405,20 +64480,26 @@ static void generateColumnTypes( sNC.pParse = pParse; for(i=0; inExpr; i++){ Expr *p = pEList->a[i].pExpr; + const char *zType; +#ifdef SQLITE_ENABLE_COLUMN_METADATA const char *zOrigDb = 0; const char *zOrigTab = 0; const char *zOrigCol = 0; - const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); /* The vdbe must make its own copy of the column-type and other ** column specific strings, in case the schema is reset before this ** virtual machine is deleted. */ - sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P4_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT); +#else + zType = columnType(&sNC, p, 0, 0, 0); +#endif + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT); } +#endif /* SQLITE_OMIT_DECLTYPE */ } /* @@ -62852,10 +64933,12 @@ static int prepSelectStmt(Parse *pParse, Select *p){ sqlite3ExprListDelete(pEList); p->pEList = pNew; } - if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){ +#if SQLITE_MAX_COLUMN + if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); rc = SQLITE_ERROR; } +#endif if( db->mallocFailed ){ rc = SQLITE_NOMEM; } @@ -62982,11 +65065,13 @@ static int processOrderGroupBy( ExprList *pEList; if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; - if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){ +#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ const char *zType = isOrder ? "ORDER" : "GROUP"; sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); return 1; } +#endif pEList = pSelect->pEList; if( pEList==0 ){ return 0; @@ -63049,11 +65134,13 @@ static int processCompoundOrderBy( pOrderBy = pSelect->pOrderBy; if( pOrderBy==0 ) return 0; - if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){ + db = pParse->db; +#if SQLITE_MAX_COLUMN + if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); return 1; } - db = pParse->db; +#endif for(i=0; inExpr; i++){ pOrderBy->a[i].done = 0; } @@ -63653,6 +65740,7 @@ static int multiSelect( multi_select_end: pDest->iMem = dest.iMem; + pDest->nMem = dest.nMem; return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ @@ -64029,7 +66117,7 @@ static int flattenSubquery( /* ** Analyze the SELECT statement passed as an argument to see if it -** is a min() or max() query. Return ORDERBY_MIN or ORDERBY_MAX if +** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if ** it is, or 0 otherwise. At present, a query is considered to be ** a min()/max() query if: ** @@ -64042,18 +66130,18 @@ static int minMaxQuery(Parse *pParse, Select *p){ Expr *pExpr; ExprList *pEList = p->pEList; - if( pEList->nExpr!=1 ) return ORDERBY_NORMAL; + if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL; pExpr = pEList->a[0].pExpr; pEList = pExpr->pList; if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0; - if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return ORDERBY_NORMAL; - if( pExpr->token.n!=3 ) return ORDERBY_NORMAL; + if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; + if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL; if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ - return ORDERBY_MIN; + return WHERE_ORDERBY_MIN; }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ - return ORDERBY_MAX; + return WHERE_ORDERBY_MAX; } - return ORDERBY_NORMAL; + return WHERE_ORDERBY_NORMAL; } /* @@ -64254,7 +66342,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pList, regAgg); + sqlite3ExprCodeExprList(pParse, pList, regAgg, 0); }else{ nArg = 0; regAgg = 0; @@ -64281,6 +66369,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ (void*)pF->pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg); + sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); if( addrNext ){ sqlite3VdbeResolveLabel(v, addrNext); } @@ -64291,7 +66380,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ pAggInfo->directMode = 0; } -#ifndef SQLITE_OMIT_TRIGGER +#if 0 /* ** This function is used when a SELECT statement is used to create a ** temporary table for iterating through when running an INSTEAD OF @@ -64441,12 +66530,14 @@ SQLITE_PRIVATE int sqlite3Select( if( p->pRightmost==0 ){ Select *pLoop, *pRight = 0; int cnt = 0; + int mxSelect; for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){ pLoop->pRightmost = p; pLoop->pNext = pRight; pRight = pLoop; } - if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){ + mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; + if( mxSelect && cnt>mxSelect ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); return 1; } @@ -64509,7 +66600,6 @@ SQLITE_PRIVATE int sqlite3Select( }else{ needRestoreContext = 0; } -#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 /* Increment Parse.nHeight by the height of the largest expression ** tree refered to by this, the parent select. The child select ** may contain expression trees of at most @@ -64518,15 +66608,12 @@ SQLITE_PRIVATE int sqlite3Select( ** an exact limit. */ pParse->nHeight += sqlite3SelectExprHeight(p); -#endif sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0); if( db->mallocFailed ){ goto select_end; } -#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 pParse->nHeight -= sqlite3SelectExprHeight(p); -#endif if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; } @@ -64698,10 +66785,9 @@ SQLITE_PRIVATE int sqlite3Select( */ sAggInfo.sortingIdx = pParse->nTab++; pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); - addrSortingIdx = - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sAggInfo.sortingIdx, - sAggInfo.nSortingColumn, 0, - (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, + sAggInfo.sortingIdx, sAggInfo.nSortingColumn, + 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF); /* Initialize memory locations used by GROUP BY aggregate processing */ @@ -64786,14 +66872,18 @@ SQLITE_PRIVATE int sqlite3Select( } } regBase = sqlite3GetTempRange(pParse, nCol); - sqlite3ExprCodeExprList(pParse, pGroupBy, regBase); + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); j = nGroupBy+1; for(i=0; iiSorterColumn>=j ){ - sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable, - j + regBase); + int r1 = j + regBase; + int r2 = sqlite3ExprCodeGetColumn(pParse, + pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); + if( r1!=r2 ){ + sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); + } j++; } } @@ -64843,7 +66933,7 @@ SQLITE_PRIVATE int sqlite3Select( */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; jnExpr; j++){ - sqlite3VdbeAddOp2(v, OP_Move, iBMem+j, iAMem+j); + sqlite3ExprCodeMove(pParse, iBMem+j, iAMem+j); } sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow); VdbeComment((v, "output one row")); @@ -64909,7 +66999,7 @@ SQLITE_PRIVATE int sqlite3Select( if( flag ){ pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList); if( pMinMax && !db->mallocFailed ){ - pMinMax->a[0].sortOrder = ((flag==ORDERBY_MIN)?0:1); + pMinMax->a[0].sortOrder = ((flag==WHERE_ORDERBY_MIN)?0:1); pMinMax->a[0].pExpr->op = TK_COLUMN; } } @@ -64927,7 +67017,7 @@ SQLITE_PRIVATE int sqlite3Select( updateAccumulator(pParse, &sAggInfo); if( !pMinMax && flag ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); - VdbeComment((v, "%s() by index", (flag==ORDERBY_MIN?"min":"max"))); + VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); @@ -65005,7 +67095,7 @@ select_end: ** code base. Then are intended to be called from within the debugger ** or from temporary "printf" statements inserted for debugging. */ -static void sqlite3PrintExpr(Expr *p){ +SQLITE_PRIVATE void sqlite3PrintExpr(Expr *p){ if( p->token.z && p->token.n>0 ){ sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z); }else{ @@ -65021,7 +67111,7 @@ static void sqlite3PrintExpr(Expr *p){ } sqlite3DebugPrintf(")"); } -static void sqlite3PrintExprList(ExprList *pList){ +SQLITE_PRIVATE void sqlite3PrintExprList(ExprList *pList){ int i; for(i=0; inExpr; i++){ sqlite3PrintExpr(pList->a[i].pExpr); @@ -65030,7 +67120,7 @@ static void sqlite3PrintExprList(ExprList *pList){ } } } -static void sqlite3PrintSelect(Select *p, int indent){ +SQLITE_PRIVATE void sqlite3PrintSelect(Select *p, int indent){ sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p); sqlite3PrintExprList(p->pEList); sqlite3DebugPrintf("\n"); @@ -65232,7 +67322,7 @@ SQLITE_API int sqlite3_get_table( res.azResult[0] = 0; rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); - res.azResult[0] = (char*)(sqlite3_intptr_t)res.nData; + res.azResult[0] = (char*)res.nData; if( (rc&0xff)==SQLITE_ABORT ){ sqlite3_free_table(&res.azResult[1]); if( res.zErrMsg ){ @@ -65274,10 +67364,10 @@ SQLITE_API void sqlite3_free_table( char **azResult /* Result returned from from sqlite3_get_table() */ ){ if( azResult ){ - sqlite3_intptr_t i, n; + int i, n; azResult--; assert( azResult!=0 ); - n = (sqlite3_intptr_t)azResult[0]; + n = (int)azResult[0]; for(i=1; inCol); sqlite3VdbeAddOp2(v, OP_OpenPseudo, oldIdx, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); iGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); addr = sqlite3VdbeMakeLabel(v); @@ -66469,8 +68560,7 @@ SQLITE_PRIVATE void sqlite3Update( ** a ephemeral table. */ if( isView ){ - sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, - old_col_mask|new_col_mask, iCur); + sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur); } /* Resolve the column names in all the expressions in the @@ -66482,13 +68572,16 @@ SQLITE_PRIVATE void sqlite3Update( /* Begin the database scan */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); + sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, + WHERE_ONEPASS_DESIRED); if( pWInfo==0 ) goto update_cleanup; + okOnePass = pWInfo->okOnePass; /* Remember the rowid of every item to be updated. */ - sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid,iCur,regOldRowid); - sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0); + sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid); + if( !okOnePass ) sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0); /* End the database scan loop. */ @@ -66508,7 +68601,7 @@ SQLITE_PRIVATE void sqlite3Update( ** action, then we need to open all indices because we might need ** to be deleting some records. */ - sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); + if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); if( onError==OE_Replace ){ openAll = 1; }else{ @@ -66536,7 +68629,13 @@ SQLITE_PRIVATE void sqlite3Update( } /* Top of the update loop */ - addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0); + if( okOnePass ){ + int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid); + addr = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, a1); + }else{ + addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0); + } if( triggers_exist ){ int regRowid; @@ -66587,6 +68686,7 @@ SQLITE_PRIVATE void sqlite3Update( sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow); if( !isView ){ sqlite3TableAffinityStr(v, pTab); + sqlite3ExprCacheAffinityChange(pParse, regCols, pTab->nCol); } sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); if( pParse->nErr ) goto update_cleanup; @@ -66792,7 +68892,7 @@ static void updateVirtualTable( for(i=0; inCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i); } - pParse->pVirtualLock = pTab; + sqlite3VtabMakeWritable(pParse, pTab); sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVtab, P4_VTAB); sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr); sqlite3VdbeJumpHere(v, addr-1); @@ -66803,6 +68903,11 @@ static void updateVirtualTable( } #endif /* SQLITE_OMIT_VIRTUALTABLE */ +/* Make sure "isView" gets undefined in case this file becomes part of +** the amalgamation - so that subsequent files do not see isView as a +** macro. */ +#undef isView + /************** End of update.c **********************************************/ /************** Begin file vacuum.c ******************************************/ /* @@ -66821,7 +68926,7 @@ static void updateVirtualTable( ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.76 2008/01/03 00:01:25 drh Exp $ +** $Id: vacuum.c,v 1.78 2008/04/30 16:38:23 drh Exp $ */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) @@ -66890,6 +68995,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ char *zSql = 0; /* SQL statements */ int saved_flags; /* Saved value of the db->flags */ Db *pDb = 0; /* Database to detach at end of vacuum */ + int nRes; /* Save the current value of the write-schema flag before setting it. */ saved_flags = db->flags; @@ -66910,6 +69016,12 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** sqlite3BtreeCopyFile() is called. ** ** An optimisation would be to use a non-journaled pager. + ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but + ** that actually made the VACUUM run slower. Very little journalling + ** actually occurs when doing a vacuum since the vacuum_db is initially + ** empty. Only the journal header is written. Apparently it takes more + ** time to parse and run the PRAGMA to turn journalling off than it does + ** to write the journal header file. */ zSql = "ATTACH '' AS vacuum_db;"; rc = execSql(db, zSql); @@ -66917,13 +69029,15 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ pDb = &db->aDb[db->nDb-1]; assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); pTemp = db->aDb[db->nDb-1].pBt; - sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), - sqlite3BtreeGetReserve(pMain)); - if( db->mallocFailed ){ + + nRes = sqlite3BtreeGetReserve(pMain); + if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes) + || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes) + || db->mallocFailed + ){ rc = SQLITE_NOMEM; goto end_of_vacuum; } - assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); if( rc!=SQLITE_OK ){ goto end_of_vacuum; @@ -67042,6 +69156,10 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ rc = sqlite3BtreeCommit(pMain); } + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes); + } + end_of_vacuum: /* Restore the original value of db->flags */ db->flags = saved_flags; @@ -67082,7 +69200,7 @@ end_of_vacuum: ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.65 2008/03/06 09:58:50 mlcreech Exp $ +** $Id: vtab.c,v 1.69 2008/05/05 13:23:04 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -67666,6 +69784,13 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab } (void)sqlite3SafetyOn(db); if( rc==SQLITE_OK ){ + int i; + for(i=0; inVTrans; i++){ + if( db->aVTrans[i]==pTab->pVtab ){ + db->aVTrans[i] = db->aVTrans[--db->nVTrans]; + break; + } + } pTab->pVtab = 0; } } @@ -67681,7 +69806,7 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab ** ** The array is cleared after invoking the callbacks. */ -static void callFinaliser(sqlite3 *db, sqlite3_intptr_t offset){ +static void callFinaliser(sqlite3 *db, int offset){ int i; if( db->aVTrans ){ for(i=0; inVTrans && db->aVTrans[i]; i++){ @@ -67734,7 +69859,7 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, int rc2){ ** sqlite3.aVTrans array. Then clear the array itself. */ SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){ - callFinaliser(db, (sqlite3_intptr_t)(&((sqlite3_module *)0)->xRollback)); + callFinaliser(db, offsetof(sqlite3_module,xRollback)); return SQLITE_OK; } @@ -67743,7 +69868,7 @@ SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){ ** sqlite3.aVTrans array. Then clear the array itself. */ SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){ - callFinaliser(db, (sqlite3_intptr_t)(&((sqlite3_module *)0)->xCommit)); + callFinaliser(db, offsetof(sqlite3_module,xCommit)); return SQLITE_OK; } @@ -67865,6 +69990,27 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( return pNew; } +/* +** Make sure virtual table pTab is contained in the pParse->apVirtualLock[] +** array so that an OP_VBegin will get generated for it. Add pTab to the +** array if it is missing. If pTab is already in the array, this routine +** is a no-op. +*/ +SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ + int i, n; + assert( IsVirtual(pTab) ); + for(i=0; inVtabLock; i++){ + if( pTab==pParse->apVtabLock[i] ) return; + } + n = (pParse->nVtabLock+1)*sizeof(pParse->apVtabLock[0]); + pParse->apVtabLock = sqlite3_realloc(pParse->apVtabLock, n); + if( pParse->apVtabLock ){ + pParse->apVtabLock[pParse->nVtabLock++] = pTab; + }else{ + pParse->db->mallocFailed = 1; + } +} + #endif /* SQLITE_OMIT_VIRTUALTABLE */ /************** End of vtab.c ************************************************/ @@ -67887,7 +70033,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction( ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.290 2008/03/17 17:08:33 drh Exp $ +** $Id: where.c,v 1.302 2008/04/19 14:40:44 drh Exp $ */ /* @@ -68405,7 +70551,8 @@ static int isLikeOrGlob( #endif pList = pExpr->pList; pRight = pList->a[0].pExpr; - if( pRight->op!=TK_STRING ){ + if( pRight->op!=TK_STRING + && (pRight->op!=TK_REGISTER || pRight->iColumn!=TK_STRING) ){ return 0; } pLeft = pList->a[1].pExpr; @@ -68587,6 +70734,7 @@ static void exprAnalyze( Expr *pExpr; Bitmask prereqLeft; Bitmask prereqAll; + Bitmask extraRight = 0; int nPattern; int isComplete; int noCase; @@ -68613,7 +70761,10 @@ static void exprAnalyze( } prereqAll = exprTableUsage(pMaskSet, pExpr); if( ExprHasProperty(pExpr, EP_FromJoin) ){ - prereqAll |= getMask(pMaskSet, pExpr->iRightJoinTable); + Bitmask x = getMask(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 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; @@ -68842,6 +70993,11 @@ or_not_possible: } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ + + /* Prevent ON clause terms of a LEFT JOIN from being used to drive + ** an index for tables to the left of the join. + */ + pTerm->prereqRight |= extraRight; } /* @@ -69132,8 +71288,10 @@ static double bestVirtualIndex( ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->eOperator==WO_IN ) continue; - if( pTerm->eOperator==WO_ISNULL ) continue; + if( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; nTerm++; } @@ -69180,8 +71338,10 @@ static double bestVirtualIndex( for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->eOperator==WO_IN ) continue; - if( pTerm->eOperator==WO_ISNULL ) continue; + if( (pTerm->eOperator&(pTerm->eOperator-1))==0 ); + testcase( pTerm->eOperator==WO_IN ); + testcase( pTerm->eOperator==WO_ISNULL ); + if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue; pIdxCons[j].iColumn = pTerm->leftColumn; pIdxCons[j].iTermOffset = i; pIdxCons[j].op = pTerm->eOperator; @@ -69587,24 +71747,17 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ } /* -** Generate code that builds a probe for an index. -** -** There should be nColumn values on the stack. The index -** to be probed is pIdx. Pop the values from the stack and -** replace them all with a single record that is the index -** problem. +** Apply the affinities associated with the first n columns of index +** pIdx to the values in the n registers starting at base. */ -static void buildIndexProbe( - Vdbe *v, /* Generate code into this VM */ - int nColumn, /* The number of columns to check for NULL */ - Index *pIdx, /* Index that we will be searching */ - int regSrc, /* Take values from this register */ - int regDest /* Write the result into this register */ -){ - assert( regSrc>0 ); - assert( regDest>0 ); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest); - sqlite3IndexAffinityStr(v, pIdx); +static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){ + if( n>0 ){ + Vdbe *v = pParse->pVdbe; + assert( v!=0 ); + sqlite3VdbeAddOp2(v, OP_Affinity, base, n); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ExprCacheAffinityChange(pParse, base, n); + } } @@ -69619,19 +71772,23 @@ static void buildIndexProbe( ** result is left on the stack. For constraints of the form X IN (...) ** this routine sets up a loop that will iterate over all values of X. */ -static void codeEqualityTerm( +static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ WhereLevel *pLevel, /* When level of the FROM clause we are working on */ - int iReg /* Leave results in this register */ + int iTarget /* Attempt to leave results in this register */ ){ Expr *pX = pTerm->pExpr; Vdbe *v = pParse->pVdbe; + int iReg; /* Register holding results */ - assert( iReg>0 && iReg<=pParse->nMem ); + if( iTarget<=0 ){ + iReg = iTarget = sqlite3GetTempReg(pParse); + } if( pX->op==TK_EQ ){ - sqlite3ExprCode(pParse, pX->pRight, iReg); + iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ + iReg = iTarget; sqlite3VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE_OMIT_SUBQUERY }else{ @@ -69640,6 +71797,7 @@ static void codeEqualityTerm( struct InLoop *pIn; assert( pX->op==TK_IN ); + iReg = iTarget; eType = sqlite3FindInIndex(pParse, pX, 1); iTab = pX->iTable; sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); @@ -69666,6 +71824,7 @@ static void codeEqualityTerm( #endif } disableTerm(pLevel, pTerm); + return iReg; } /* @@ -69719,11 +71878,17 @@ static int codeAllEqualityTerms( */ assert( pIdx->nColumn>=nEq ); for(j=0; jaiColumn[j]; pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx); if( pTerm==0 ) break; assert( (pTerm->flags & TERM_CODED)==0 ); - codeEqualityTerm(pParse, pTerm, pLevel, regBase+j); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j); + if( r1!=regBase+j ){ + sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j); + } + testcase( pTerm->eOperator & WO_ISNULL ); + testcase( pTerm->eOperator & WO_IN ); if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk); } @@ -69855,7 +72020,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */ - u8 obflag /* One of ORDERBY_MIN, ORDERBY_MAX or ORDERBY_NORMAL */ + u8 wflags /* One of the WHERE_* flags defined in sqliteInt.h */ ){ int i; /* Loop counter */ WhereInfo *pWInfo; /* Will become the return value of this function */ @@ -69889,6 +72054,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ initMaskSet(&maskSet); whereClauseInit(&wc, pParse, &maskSet); + sqlite3ExprCodeConstants(pParse, pWhere); whereSplit(&wc, pWhere, TK_AND); /* Allocate and initialize the WhereInfo structure that will become the @@ -69913,14 +72079,36 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pWhere = 0; } + /* Assign a bit from the bitmask to every term in the FROM clause. + ** + ** When assigning bitmask values to FROM clause cursors, it must be + ** the case that if X is the bitmask for the N-th FROM clause term then + ** the bitmask for all FROM clause terms to the left of the N-th term + ** is (X-1). An expression from the ON clause of a LEFT JOIN can use + ** its Expr.iRightJoinTable value to find the bitmask of the right table + ** of the join. Subtracting one from the right table bitmask gives a + ** bitmask for all tables to the left of the join. Knowing the bitmask + ** for all tables to the left of a left join is important. Ticket #3015. + */ + for(i=0; inSrc; i++){ + createMask(&maskSet, pTabList->a[i].iCursor); + } +#ifndef NDEBUG + { + Bitmask toTheLeft = 0; + for(i=0; inSrc; i++){ + Bitmask m = getMask(&maskSet, pTabList->a[i].iCursor); + assert( (m-1)==toTheLeft ); + toTheLeft |= m; + } + } +#endif + /* Analyze all of the subexpressions. Note that exprAnalyze() might ** add new virtual terms onto the end of the WHERE clause. We do not ** want to analyze these virtual terms, so start analyzing at the end ** and work forward so that the added virtual terms are never processed. */ - for(i=0; inSrc; i++){ - createMask(&maskSet, pTabList->a[i].iCursor); - } exprAnalyzeAll(pTabList, &wc); if( db->mallocFailed ){ goto whereBeginNoMem; @@ -70040,6 +72228,17 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( *ppOrderBy = 0; } + /* If the caller is an UPDATE or DELETE statement that is requesting + ** to use a one-pass algorithm, determine if this is appropriate. + ** The one-pass algorithm only works if the WHERE clause constraints + ** the statement to update a single row. + */ + assert( (wflags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); + if( (wflags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){ + pWInfo->okOnePass = 1; + pWInfo->a[0].flags &= ~WHERE_IDX_ONLY; + } + /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ @@ -70088,12 +72287,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( }else #endif if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ - sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead); - if( pTab->nCol<(sizeof(Bitmask)*8) ){ + int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; + sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); + if( !pWInfo->okOnePass && pTab->nCol<(sizeof(Bitmask)*8) ){ Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} - sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n); + sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-2, n); assert( n<=pTab->nCol ); } }else{ @@ -70103,10 +72303,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( (pIx = pLevel->pIdx)!=0 ){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); assert( pIx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIx->nColumn+1); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIx->zName)); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1); } sqlite3CodeVerifySchema(pParse, iDb); } @@ -70212,13 +72412,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( assert( pTerm->pExpr!=0 ); assert( pTerm->leftCursor==iCur ); assert( omitTable==0 ); - r1 = sqlite3GetTempReg(pParse); - codeEqualityTerm(pParse, pTerm, pLevel, r1); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, 0); nxt = pLevel->nxt; - sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, nxt, 1); + sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1); VdbeComment((v, "pk")); - sqlite3ReleaseTempReg(pParse, r1); pLevel->op = OP_Noop; }else if( pLevel->flags & WHERE_ROWID_RANGE ){ /* Case 2: We have an inequality comparison against the ROWID field. @@ -70277,48 +72475,72 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL); sqlite3ReleaseTempReg(pParse, r1); } - }else if( pLevel->flags & WHERE_COLUMN_RANGE ){ - /* Case 3: The WHERE clause term that refers to the right-most - ** column of the index is an inequality. For example, if - ** the index is on (x,y,z) and the WHERE clause is of the - ** form "x=5 AND y<10" then this case is used. Only the - ** right-most column can be an inequality - the rest must - ** use the "==" and "IN" operators. + }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){ + /* Case 3: A scan using an index. + ** + ** The WHERE clause may contain zero or more equality + ** terms ("==" or "IN" operators) that refer to the N + ** left-most columns of the index. It may also contain + ** inequality constraints (>, <, >= or <=) on the indexed + ** column that immediately follows the N equalities. Only + ** the right-most column can be an inequality - the rest must + ** use the "==" and "IN" operators. For example, if the + ** index is on (x,y,z), then the following clauses are all + ** optimized: + ** + ** x=5 + ** x=5 AND y=10 + ** x=5 AND y<10 + ** x=5 AND y>5 AND y<10 + ** x=5 AND y=5 AND z<=10 + ** + ** The z<10 term of the following cannot be used, only + ** the x=5 term: + ** + ** x=5 AND z<10 + ** + ** N may be zero if there are inequality constraints. + ** If there are no inequality constraints, then N is at + ** least one. ** ** This case is also used when there are no WHERE clause ** constraints but an index is selected anyway, in order ** to force the output order to conform to an ORDER BY. - */ - int start; + */ + int aStartOp[] = { + 0, + 0, + OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */ + OP_Last, /* 3: (!start_constraints && startEq && bRev) */ + OP_MoveGt, /* 4: (start_constraints && !startEq && !bRev) */ + OP_MoveLt, /* 5: (start_constraints && !startEq && bRev) */ + OP_MoveGe, /* 6: (start_constraints && startEq && !bRev) */ + OP_MoveLe /* 7: (start_constraints && startEq && bRev) */ + }; + int aEndOp[] = { + OP_Noop, /* 0: (!end_constraints) */ + OP_IdxGE, /* 1: (end_constraints && !bRev) */ + OP_IdxLT /* 2: (end_constraints && bRev) */ + }; int nEq = pLevel->nEq; - int topEq=0; /* True if top limit uses ==. False is strictly < */ - int btmEq=0; /* True if btm limit uses ==. False if strictly > */ - int topOp, btmOp; /* Operators for the top and bottom search bounds */ - int testOp; - int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0; - int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0; - int isMinQuery = 0; /* If this is an optimized SELECT min(x) ... */ - int regBase; /* Base register holding constraint values */ - int r1; /* Temp register */ + int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ + int regBase; /* Base register holding constraint values */ + int r1; /* Temp register */ + WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ + WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ + int startEq; /* True if range start uses ==, >= or <= */ + int endEq; /* True if range end uses ==, >= or <= */ + int start_constraints; /* Start of range is constrained */ + int k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */ + int nConstraint; /* Number of constraint terms */ + int op; /* Generate code to evaluate all constraint terms using == or IN - ** and level the values of those terms on the stack. + ** and store the values of those terms in an array of registers + ** starting at regBase. */ regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 2); - - /* Figure out what comparison operators to use for top and bottom - ** search bounds. For an ascending index, the bottom bound is a > or >= - ** operator and the top bound is a < or <= operator. For a descending - ** index the operators are reversed. - */ - if( pIdx->aSortOrder[nEq]==SQLITE_SO_ASC ){ - topOp = WO_LT|WO_LE; - btmOp = WO_GT|WO_GE; - }else{ - topOp = WO_GT|WO_GE; - btmOp = WO_LT|WO_LE; - SWAP(int, topLimit, btmLimit); - } + nxt = pLevel->nxt; /* If this loop satisfies a sort order (pOrderBy) request that ** was passed to this function to implement a "SELECT min(x) ..." @@ -70328,7 +72550,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** the first one after the nEq equality constraints in the index, ** this requires some special handling. */ - if( (obflag==ORDERBY_MIN) + if( (wflags&WHERE_ORDERBY_MIN)!=0 && (pLevel->flags&WHERE_ORDERBY) && (pIdx->nColumn>nEq) && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq]) @@ -70336,194 +72558,112 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( isMinQuery = 1; } - /* Generate the termination key. This is the key value that - ** will end the search. There is no termination key if there - ** are no equality terms and no "X<..." term. - ** - ** 2002-Dec-04: On a reverse-order scan, the so-called "termination" - ** key computed here really ends up being the start key. + /* Find any inequality constraint terms for the start and end + ** of the range. */ - nxt = pLevel->nxt; - if( topLimit ){ - Expr *pX; - int k = pIdx->aiColumn[nEq]; - pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx); - assert( pTerm!=0 ); - pX = pTerm->pExpr; - assert( (pTerm->flags & TERM_CODED)==0 ); - sqlite3ExprCode(pParse, pX->pRight, regBase+nEq); - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); - topEq = pTerm->eOperator & (WO_LE|WO_GE); - disableTerm(pLevel, pTerm); - testOp = OP_IdxGE; - }else{ - testOp = nEq>0 ? OP_IdxGE : OP_Noop; - topEq = 1; - } - if( testOp!=OP_Noop || (isMinQuery&&bRev) ){ - int nCol = nEq + topLimit; - if( isMinQuery && !topLimit ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol); - nCol++; - topEq = 0; - } - buildIndexProbe(v, nCol, pIdx, regBase, pLevel->iMem); - if( bRev ){ - int op = topEq ? OP_MoveLe : OP_MoveLt; - sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, pLevel->iMem); - } - }else if( bRev ){ - sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk); + if( pLevel->flags & WHERE_TOP_LIMIT ){ + pRangeEnd = findTerm(&wc, iCur, k, notReady, (WO_LT|WO_LE), pIdx); } - - /* Generate the start key. This is the key that defines the lower - ** bound on the search. There is no start key if there are no - ** equality terms and if there is no "X>..." term. In - ** that case, generate a "Rewind" instruction in place of the - ** start key search. - ** - ** 2002-Dec-04: In the case of a reverse-order search, the so-called - ** "start" key really ends up being used as the termination key. - */ - if( btmLimit ){ - Expr *pX; - int k = pIdx->aiColumn[nEq]; - pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx); - assert( pTerm!=0 ); - pX = pTerm->pExpr; - assert( (pTerm->flags & TERM_CODED)==0 ); - sqlite3ExprCode(pParse, pX->pRight, regBase+nEq); - sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); - btmEq = pTerm->eOperator & (WO_LE|WO_GE); - disableTerm(pLevel, pTerm); - }else{ - btmEq = 1; - } - if( nEq>0 || btmLimit || (isMinQuery&&!bRev) ){ - int nCol = nEq + btmLimit; - if( isMinQuery && !btmLimit ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol); - nCol++; - btmEq = 0; - } - if( bRev ){ - r1 = pLevel->iMem; - testOp = OP_IdxLT; - }else{ - r1 = sqlite3GetTempReg(pParse); - } - buildIndexProbe(v, nCol, pIdx, regBase, r1); - if( !bRev ){ - int op = btmEq ? OP_MoveGe : OP_MoveGt; - sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1); - sqlite3ReleaseTempReg(pParse, r1); - } - }else if( bRev ){ - testOp = OP_Noop; - }else{ - sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, brk); + if( pLevel->flags & WHERE_BTM_LIMIT ){ + pRangeStart = findTerm(&wc, iCur, k, notReady, (WO_GT|WO_GE), pIdx); } - /* Generate the the top of the loop. If there is a termination - ** key we have to test for that key and abort at the top of the - ** loop. + /* If we are doing a reverse order scan on an ascending index, or + ** a forward order scan on a descending index, interchange the + ** start and end terms (pRangeStart and pRangeEnd). */ - start = sqlite3VdbeCurrentAddr(v); - if( testOp!=OP_Noop ){ - sqlite3VdbeAddOp3(v, testOp, iIdxCur, nxt, pLevel->iMem); - if( (topEq && !bRev) || (!btmEq && bRev) ){ - sqlite3VdbeChangeP5(v, 1); + if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){ + SWAP(WhereTerm *, pRangeEnd, pRangeStart); + } + + testcase( pRangeStart && pRangeStart->eOperator & WO_LE ); + testcase( pRangeStart && pRangeStart->eOperator & WO_GE ); + testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE ); + testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE ); + startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); + endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); + start_constraints = pRangeStart || nEq>0; + + /* Seek the index cursor to the start of the range. */ + nConstraint = nEq; + if( pRangeStart ){ + int dcc = pParse->disableColCache; + if( pRangeEnd ){ + pParse->disableColCache = 1; } + sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq); + pParse->disableColCache = dcc; + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); + nConstraint++; + }else if( isMinQuery ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + nConstraint++; + startEq = 0; + start_constraints = 1; + } + codeApplyAffinity(pParse, regBase, nConstraint, pIdx); + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; + assert( op!=0 ); + testcase( op==OP_Rewind ); + testcase( op==OP_Last ); + testcase( op==OP_MoveGt ); + testcase( op==OP_MoveGe ); + testcase( op==OP_MoveLe ); + testcase( op==OP_MoveLt ); + sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, + (char*)nConstraint, P4_INT32); + + /* Load the value for the inequality constraint at the end of the + ** range (if any). + */ + nConstraint = nEq; + if( pRangeEnd ){ + sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq); + sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt); + codeApplyAffinity(pParse, regBase, nEq+1, pIdx); + nConstraint++; } + + /* Top of the loop body */ + pLevel->p2 = sqlite3VdbeCurrentAddr(v); + + /* Check if the index cursor is past the end of the range. */ + op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)]; + testcase( op==OP_Noop ); + testcase( op==OP_IdxGE ); + testcase( op==OP_IdxLT ); + sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, + (char*)nConstraint, P4_INT32); + sqlite3VdbeChangeP5(v, endEq!=bRev); + + /* If there are inequality constraints, check that the value + ** of the table column that the inequality contrains is not NULL. + ** If it is, jump to the next iteration of the loop. + */ r1 = sqlite3GetTempReg(pParse); - if( topLimit | btmLimit ){ + testcase( pLevel->flags & WHERE_BTM_LIMIT ); + testcase( pLevel->flags & WHERE_TOP_LIMIT ); + if( pLevel->flags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1); sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont); } + + /* Seek the table cursor, if required */ if( !omitTable ){ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1); sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1); /* Deferred seek */ } sqlite3ReleaseTempReg(pParse, r1); - /* Record the instruction used to terminate the loop. + /* Record the instruction used to terminate the loop. Disable + ** WHERE clause terms made redundant by the index range scan. */ pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iIdxCur; - pLevel->p2 = start; - }else if( pLevel->flags & WHERE_COLUMN_EQ ){ - /* Case 4: There is an index and all terms of the WHERE clause that - ** refer to the index using the "==" or "IN" operators. - */ - int start; - int nEq = pLevel->nEq; - int isMinQuery = 0; /* If this is an optimized SELECT min(x) ... */ - int regBase; /* Base register of array holding constraints */ - int r1; - - /* Generate code to evaluate all constraint terms using == or IN - ** and leave the values of those terms on the stack. - */ - regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1); - nxt = pLevel->nxt; - - if( (obflag==ORDERBY_MIN) - && (pLevel->flags&WHERE_ORDERBY) - && (pIdx->nColumn>nEq) - && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq]) - ){ - isMinQuery = 1; - buildIndexProbe(v, nEq, pIdx, regBase, pLevel->iMem); - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - r1 = ++pParse->nMem; - buildIndexProbe(v, nEq+1, pIdx, regBase, r1); - }else{ - /* Generate a single key that will be used to both start and - ** terminate the search - */ - r1 = pLevel->iMem; - buildIndexProbe(v, nEq, pIdx, regBase, r1); - } - - /* Generate code (1) to move to the first matching element of the table. - ** Then generate code (2) that jumps to "nxt" after the cursor is past - ** the last matching element of the table. The code (1) is executed - ** once to initialize the search, the code (2) is executed before each - ** iteration of the scan to see if the scan has finished. */ - if( bRev ){ - /* Scan in reverse order */ - int op; - if( isMinQuery ){ - op = OP_MoveLt; - }else{ - op = OP_MoveLe; - } - sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1); - start = sqlite3VdbeAddOp3(v, OP_IdxLT, iIdxCur, nxt, pLevel->iMem); - pLevel->op = OP_Prev; - }else{ - /* Scan in the forward order */ - int op; - if( isMinQuery ){ - op = OP_MoveGt; - }else{ - op = OP_MoveGe; - } - sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1); - start = sqlite3VdbeAddOp3(v, OP_IdxGE, iIdxCur, nxt, pLevel->iMem); - sqlite3VdbeChangeP5(v, 1); - pLevel->op = OP_Next; - } - if( !omitTable ){ - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1); - sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1); /* Deferred seek */ - sqlite3ReleaseTempReg(pParse, r1); - } - pLevel->p1 = iIdxCur; - pLevel->p2 = start; + disableTerm(pLevel, pRangeStart); + disableTerm(pLevel, pRangeEnd); }else{ - /* Case 5: There is no usable index. We must do a complete + /* Case 4: There is no usable index. We must do a complete ** scan of the entire table. */ assert( omitTable==0 ); @@ -70539,6 +72679,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){ Expr *pE; + testcase( pTerm->flags & TERM_VIRTUAL ); + testcase( pTerm->flags & TERM_CODED ); if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue; pE = pTerm->pExpr; @@ -70557,7 +72699,11 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pLevel->top = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); + sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur); + sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur); for(pTerm=wc.a, j=0; jflags & TERM_VIRTUAL ); + testcase( pTerm->flags & TERM_CODED ); if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & notReady)!=0 ) continue; assert( pTerm->pExpr ); @@ -70592,6 +72738,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } sqlite3_query_plan[nQPlan++] = ' '; } + testcase( pLevel->flags & WHERE_ROWID_EQ ); + testcase( pLevel->flags & WHERE_ROWID_RANGE ); if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){ memcpy(&sqlite3_query_plan[nQPlan], "* ", 2); nQPlan += 2; @@ -70640,6 +72788,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ /* Generate loop termination code. */ + sqlite3ExprClearColumnCache(pWInfo->pParse, -1); for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqlite3VdbeResolveLabel(v, pLevel->cont); @@ -70682,7 +72831,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ Table *pTab = pTabItem->pTab; assert( pTab!=0 ); if( pTab->isEphem || pTab->pSelect ) continue; - if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ + if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } if( pLevel->pIdx!=0 ){ @@ -70857,13 +73006,17 @@ typedef union { #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 588 -#define YYNRULE 312 +#define YYNSTATE 589 +#define YYNRULE 313 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) +/* The yyzerominor constant is used to initialize instances of +** YYMINORTYPE objects to zero. */ +static const YYMINORTYPE yyzerominor; + /* Next are that tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an @@ -70912,7 +73065,7 @@ typedef union { ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 292, 901, 124, 587, 409, 172, 2, 418, 61, 61, + /* 0 */ 292, 903, 124, 588, 409, 172, 2, 418, 61, 61, /* 10 */ 61, 61, 519, 63, 63, 63, 63, 64, 64, 65, /* 20 */ 65, 65, 66, 210, 447, 212, 425, 431, 68, 63, /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210, @@ -70921,23 +73074,23 @@ static const YYACTIONTYPE yy_action[] = { /* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292, /* 70 */ 493, 494, 418, 489, 208, 82, 67, 420, 69, 154, /* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, - /* 90 */ 210, 67, 462, 69, 154, 425, 431, 573, 264, 58, + /* 90 */ 210, 67, 462, 69, 154, 425, 431, 574, 264, 58, /* 100 */ 64, 64, 65, 65, 65, 66, 210, 397, 398, 422, /* 110 */ 422, 422, 292, 60, 59, 297, 435, 436, 432, 432, /* 120 */ 62, 62, 61, 61, 61, 61, 317, 63, 63, 63, /* 130 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431, /* 140 */ 94, 65, 65, 65, 66, 210, 396, 210, 414, 34, - /* 150 */ 56, 298, 442, 443, 410, 488, 60, 59, 297, 435, - /* 160 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 490, + /* 150 */ 56, 298, 442, 443, 410, 418, 60, 59, 297, 435, + /* 160 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 208, /* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, - /* 180 */ 210, 292, 257, 524, 295, 571, 113, 408, 522, 451, - /* 190 */ 331, 317, 407, 20, 418, 340, 519, 396, 532, 531, - /* 200 */ 505, 447, 212, 570, 569, 208, 530, 425, 431, 149, - /* 210 */ 150, 397, 398, 414, 41, 211, 151, 533, 372, 489, - /* 220 */ 261, 568, 259, 420, 292, 60, 59, 297, 435, 436, + /* 180 */ 210, 292, 372, 524, 295, 572, 113, 408, 522, 451, + /* 190 */ 331, 317, 407, 20, 244, 340, 519, 396, 478, 531, + /* 200 */ 505, 447, 212, 571, 570, 245, 530, 425, 431, 149, + /* 210 */ 150, 397, 398, 414, 41, 211, 151, 533, 488, 489, + /* 220 */ 418, 568, 569, 420, 292, 60, 59, 297, 435, 436, /* 230 */ 432, 432, 62, 62, 61, 61, 61, 61, 317, 63, /* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210, - /* 250 */ 425, 431, 447, 333, 215, 422, 422, 422, 363, 418, + /* 250 */ 425, 431, 447, 333, 215, 422, 422, 422, 363, 299, /* 260 */ 414, 41, 397, 398, 366, 567, 211, 292, 60, 59, /* 270 */ 297, 435, 436, 432, 432, 62, 62, 61, 61, 61, /* 280 */ 61, 396, 63, 63, 63, 63, 64, 64, 65, 65, @@ -70946,46 +73099,46 @@ static const YYACTIONTYPE yy_action[] = { /* 310 */ 168, 60, 59, 297, 435, 436, 432, 432, 62, 62, /* 320 */ 61, 61, 61, 61, 474, 63, 63, 63, 63, 64, /* 330 */ 64, 65, 65, 65, 66, 210, 209, 480, 317, 77, - /* 340 */ 292, 239, 300, 55, 484, 230, 397, 398, 181, 547, + /* 340 */ 292, 239, 300, 55, 484, 490, 397, 398, 181, 547, /* 350 */ 494, 345, 348, 349, 67, 152, 69, 154, 339, 524, - /* 360 */ 414, 35, 350, 241, 221, 370, 425, 431, 578, 20, + /* 360 */ 414, 35, 350, 241, 221, 370, 425, 431, 579, 20, /* 370 */ 164, 118, 243, 343, 248, 344, 176, 322, 442, 443, /* 380 */ 414, 3, 80, 252, 60, 59, 297, 435, 436, 432, /* 390 */ 432, 62, 62, 61, 61, 61, 61, 174, 63, 63, /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292, /* 410 */ 221, 550, 236, 487, 510, 353, 317, 118, 243, 343, - /* 420 */ 248, 344, 176, 181, 317, 525, 345, 348, 349, 252, + /* 420 */ 248, 344, 176, 181, 317, 532, 345, 348, 349, 252, /* 430 */ 223, 415, 155, 464, 511, 425, 431, 350, 414, 34, - /* 440 */ 465, 211, 177, 175, 160, 237, 414, 34, 338, 549, + /* 440 */ 465, 211, 177, 175, 160, 525, 414, 34, 338, 549, /* 450 */ 449, 323, 168, 60, 59, 297, 435, 436, 432, 432, /* 460 */ 62, 62, 61, 61, 61, 61, 415, 63, 63, 63, /* 470 */ 63, 64, 64, 65, 65, 65, 66, 210, 292, 542, - /* 480 */ 335, 517, 504, 541, 456, 571, 302, 19, 331, 144, + /* 480 */ 335, 517, 504, 541, 456, 572, 302, 19, 331, 144, /* 490 */ 317, 390, 317, 330, 2, 362, 457, 294, 483, 373, - /* 500 */ 269, 268, 252, 570, 425, 431, 588, 391, 388, 458, - /* 510 */ 208, 495, 414, 49, 414, 49, 303, 585, 892, 159, - /* 520 */ 892, 496, 60, 59, 297, 435, 436, 432, 432, 62, + /* 500 */ 269, 268, 252, 571, 425, 431, 589, 391, 388, 458, + /* 510 */ 208, 495, 414, 49, 414, 49, 303, 586, 894, 230, + /* 520 */ 894, 496, 60, 59, 297, 435, 436, 432, 432, 62, /* 530 */ 62, 61, 61, 61, 61, 201, 63, 63, 63, 63, /* 540 */ 64, 64, 65, 65, 65, 66, 210, 292, 317, 181, - /* 550 */ 439, 255, 345, 348, 349, 370, 153, 582, 308, 251, + /* 550 */ 439, 255, 345, 348, 349, 370, 153, 583, 308, 251, /* 560 */ 309, 452, 76, 350, 78, 382, 211, 426, 427, 415, - /* 570 */ 414, 27, 319, 425, 431, 440, 1, 22, 585, 891, - /* 580 */ 396, 891, 544, 478, 320, 263, 438, 438, 429, 430, + /* 570 */ 414, 27, 319, 425, 431, 440, 1, 22, 586, 893, + /* 580 */ 396, 893, 544, 478, 320, 263, 438, 438, 429, 430, /* 590 */ 415, 60, 59, 297, 435, 436, 432, 432, 62, 62, - /* 600 */ 61, 61, 61, 61, 328, 63, 63, 63, 63, 64, - /* 610 */ 64, 65, 65, 65, 66, 210, 292, 428, 582, 374, - /* 620 */ 224, 93, 517, 9, 336, 396, 557, 396, 456, 67, - /* 630 */ 396, 69, 154, 399, 400, 401, 320, 238, 438, 438, - /* 640 */ 457, 318, 425, 431, 299, 397, 398, 320, 433, 438, - /* 650 */ 438, 581, 291, 458, 225, 327, 5, 222, 546, 292, + /* 600 */ 61, 61, 61, 61, 237, 63, 63, 63, 63, 64, + /* 610 */ 64, 65, 65, 65, 66, 210, 292, 428, 583, 374, + /* 620 */ 224, 93, 517, 9, 159, 396, 557, 396, 456, 67, + /* 630 */ 396, 69, 154, 399, 400, 401, 320, 328, 438, 438, + /* 640 */ 457, 336, 425, 431, 361, 397, 398, 320, 433, 438, + /* 650 */ 438, 582, 291, 458, 238, 327, 318, 222, 546, 292, /* 660 */ 60, 59, 297, 435, 436, 432, 432, 62, 62, 61, - /* 670 */ 61, 61, 61, 395, 63, 63, 63, 63, 64, 64, + /* 670 */ 61, 61, 61, 225, 63, 63, 63, 63, 64, 64, /* 680 */ 65, 65, 65, 66, 210, 425, 431, 482, 313, 392, - /* 690 */ 397, 398, 397, 398, 207, 397, 398, 824, 273, 517, + /* 690 */ 397, 398, 397, 398, 207, 397, 398, 825, 273, 517, /* 700 */ 251, 200, 292, 60, 59, 297, 435, 436, 432, 432, /* 710 */ 62, 62, 61, 61, 61, 61, 470, 63, 63, 63, /* 720 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431, - /* 730 */ 171, 160, 263, 263, 304, 415, 276, 119, 274, 263, + /* 730 */ 171, 160, 263, 263, 304, 415, 276, 395, 274, 263, /* 740 */ 517, 517, 263, 517, 192, 292, 60, 70, 297, 435, /* 750 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 379, /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, @@ -70995,58 +73148,58 @@ static const YYACTIONTYPE yy_action[] = { /* 800 */ 61, 61, 371, 63, 63, 63, 63, 64, 64, 65, /* 810 */ 65, 65, 66, 210, 425, 431, 396, 275, 251, 251, /* 820 */ 172, 250, 418, 415, 386, 367, 178, 179, 180, 469, - /* 830 */ 311, 123, 156, 128, 297, 435, 436, 432, 432, 62, + /* 830 */ 311, 123, 156, 5, 297, 435, 436, 432, 432, 62, /* 840 */ 62, 61, 61, 61, 61, 317, 63, 63, 63, 63, - /* 850 */ 64, 64, 65, 65, 65, 66, 210, 72, 324, 177, + /* 850 */ 64, 64, 65, 65, 65, 66, 210, 72, 324, 194, /* 860 */ 4, 317, 263, 317, 296, 263, 415, 414, 28, 317, - /* 870 */ 263, 317, 321, 72, 324, 317, 4, 421, 445, 445, + /* 870 */ 257, 317, 321, 72, 324, 317, 4, 119, 165, 177, /* 880 */ 296, 397, 398, 414, 23, 414, 32, 418, 321, 326, - /* 890 */ 329, 414, 53, 414, 52, 317, 158, 414, 98, 451, - /* 900 */ 317, 194, 317, 277, 317, 326, 378, 471, 502, 317, - /* 910 */ 478, 279, 478, 165, 294, 451, 317, 414, 96, 75, + /* 890 */ 421, 414, 53, 414, 52, 317, 158, 414, 98, 451, + /* 900 */ 317, 263, 317, 277, 317, 326, 378, 471, 261, 317, + /* 910 */ 259, 18, 478, 445, 445, 451, 317, 414, 96, 75, /* 920 */ 74, 469, 414, 101, 414, 102, 414, 112, 73, 315, - /* 930 */ 316, 414, 114, 420, 448, 75, 74, 481, 414, 16, - /* 940 */ 381, 317, 183, 467, 73, 315, 316, 72, 324, 420, - /* 950 */ 4, 208, 317, 186, 296, 317, 499, 500, 476, 208, - /* 960 */ 173, 341, 321, 414, 99, 422, 422, 422, 423, 424, - /* 970 */ 11, 361, 380, 307, 414, 33, 415, 414, 97, 326, - /* 980 */ 460, 422, 422, 422, 423, 424, 11, 415, 413, 451, - /* 990 */ 413, 162, 412, 317, 412, 468, 226, 227, 228, 104, - /* 1000 */ 84, 473, 317, 509, 508, 317, 622, 477, 317, 75, - /* 1010 */ 74, 249, 205, 21, 281, 414, 24, 418, 73, 315, - /* 1020 */ 316, 282, 317, 420, 414, 54, 507, 414, 115, 317, - /* 1030 */ 414, 116, 506, 203, 147, 549, 244, 512, 526, 202, - /* 1040 */ 317, 513, 204, 317, 414, 117, 317, 245, 317, 18, - /* 1050 */ 317, 414, 25, 317, 256, 422, 422, 422, 423, 424, - /* 1060 */ 11, 258, 414, 36, 260, 414, 37, 317, 414, 26, - /* 1070 */ 414, 38, 414, 39, 262, 414, 40, 317, 514, 317, - /* 1080 */ 128, 317, 418, 317, 189, 377, 278, 268, 267, 414, - /* 1090 */ 42, 293, 317, 254, 317, 128, 208, 365, 8, 414, - /* 1100 */ 43, 414, 44, 414, 29, 414, 30, 352, 368, 128, - /* 1110 */ 317, 545, 317, 128, 414, 45, 414, 46, 317, 583, - /* 1120 */ 383, 553, 317, 173, 554, 317, 91, 317, 564, 369, - /* 1130 */ 91, 357, 414, 47, 414, 48, 580, 270, 290, 271, - /* 1140 */ 414, 31, 272, 556, 414, 10, 566, 414, 50, 414, - /* 1150 */ 51, 280, 283, 284, 577, 146, 463, 405, 584, 231, - /* 1160 */ 325, 419, 444, 466, 446, 246, 505, 552, 563, 515, - /* 1170 */ 516, 520, 163, 518, 394, 347, 7, 402, 403, 404, - /* 1180 */ 314, 84, 232, 334, 332, 83, 79, 416, 170, 57, - /* 1190 */ 213, 461, 125, 85, 337, 342, 492, 301, 233, 498, - /* 1200 */ 497, 105, 502, 219, 354, 247, 521, 234, 501, 235, - /* 1210 */ 287, 417, 503, 218, 527, 528, 529, 358, 240, 535, - /* 1220 */ 475, 242, 288, 479, 356, 184, 185, 121, 187, 132, - /* 1230 */ 188, 548, 537, 88, 190, 193, 364, 142, 375, 376, - /* 1240 */ 555, 133, 220, 562, 134, 310, 135, 138, 136, 574, - /* 1250 */ 575, 141, 576, 265, 579, 100, 538, 217, 393, 92, - /* 1260 */ 103, 95, 406, 623, 624, 166, 434, 167, 437, 71, - /* 1270 */ 453, 441, 450, 17, 143, 157, 169, 6, 111, 13, - /* 1280 */ 454, 455, 459, 472, 126, 81, 12, 127, 161, 485, - /* 1290 */ 486, 216, 86, 122, 106, 182, 253, 346, 312, 107, - /* 1300 */ 120, 87, 351, 108, 245, 355, 145, 536, 359, 129, - /* 1310 */ 173, 266, 191, 109, 289, 551, 130, 539, 195, 543, - /* 1320 */ 131, 14, 197, 199, 198, 558, 137, 139, 140, 110, - /* 1330 */ 15, 285, 572, 206, 389, 565, 385, 148, 586, 902, - /* 1340 */ 902, 902, 902, 902, 902, 89, 90, + /* 930 */ 316, 414, 114, 420, 294, 75, 74, 481, 414, 16, + /* 940 */ 381, 317, 279, 467, 73, 315, 316, 72, 324, 420, + /* 950 */ 4, 208, 317, 183, 296, 317, 186, 128, 84, 208, + /* 960 */ 8, 341, 321, 414, 99, 422, 422, 422, 423, 424, + /* 970 */ 11, 623, 380, 307, 414, 33, 413, 414, 97, 326, + /* 980 */ 412, 422, 422, 422, 423, 424, 11, 415, 413, 451, + /* 990 */ 415, 162, 412, 317, 499, 500, 226, 227, 228, 104, + /* 1000 */ 448, 476, 317, 173, 507, 317, 509, 508, 317, 75, + /* 1010 */ 74, 329, 205, 21, 281, 414, 24, 418, 73, 315, + /* 1020 */ 316, 282, 317, 420, 414, 54, 460, 414, 115, 317, + /* 1030 */ 414, 116, 502, 203, 147, 549, 514, 468, 128, 202, + /* 1040 */ 317, 473, 204, 317, 414, 117, 317, 477, 317, 584, + /* 1050 */ 317, 414, 25, 317, 249, 422, 422, 422, 423, 424, + /* 1060 */ 11, 506, 414, 36, 512, 414, 37, 317, 414, 26, + /* 1070 */ 414, 38, 414, 39, 526, 414, 40, 317, 254, 317, + /* 1080 */ 128, 317, 418, 317, 256, 377, 278, 268, 585, 414, + /* 1090 */ 42, 293, 317, 352, 317, 128, 208, 513, 258, 414, + /* 1100 */ 43, 414, 44, 414, 29, 414, 30, 545, 260, 128, + /* 1110 */ 317, 553, 317, 173, 414, 45, 414, 46, 317, 262, + /* 1120 */ 383, 554, 317, 91, 564, 317, 91, 317, 581, 189, + /* 1130 */ 290, 357, 414, 47, 414, 48, 267, 365, 368, 369, + /* 1140 */ 414, 31, 270, 271, 414, 10, 272, 414, 50, 414, + /* 1150 */ 51, 556, 566, 280, 283, 284, 578, 146, 419, 405, + /* 1160 */ 231, 505, 444, 325, 516, 463, 163, 446, 552, 394, + /* 1170 */ 466, 563, 246, 515, 518, 520, 402, 403, 404, 7, + /* 1180 */ 314, 84, 232, 334, 347, 83, 332, 57, 170, 79, + /* 1190 */ 213, 461, 125, 85, 337, 342, 492, 502, 497, 301, + /* 1200 */ 498, 416, 105, 219, 247, 218, 503, 501, 233, 220, + /* 1210 */ 287, 234, 527, 528, 235, 529, 417, 521, 354, 288, + /* 1220 */ 184, 121, 185, 240, 535, 475, 242, 356, 187, 479, + /* 1230 */ 188, 358, 537, 88, 190, 548, 364, 193, 132, 376, + /* 1240 */ 555, 375, 133, 134, 135, 310, 562, 138, 136, 575, + /* 1250 */ 576, 577, 580, 100, 393, 406, 217, 142, 624, 625, + /* 1260 */ 103, 141, 265, 166, 167, 434, 71, 453, 441, 437, + /* 1270 */ 450, 143, 538, 157, 120, 454, 161, 472, 455, 169, + /* 1280 */ 459, 81, 6, 12, 13, 92, 95, 126, 216, 127, + /* 1290 */ 111, 485, 486, 17, 86, 346, 106, 122, 253, 107, + /* 1300 */ 87, 108, 182, 245, 355, 145, 351, 536, 129, 359, + /* 1310 */ 312, 130, 543, 173, 539, 266, 191, 109, 289, 551, + /* 1320 */ 195, 14, 131, 198, 197, 558, 137, 199, 139, 140, + /* 1330 */ 15, 565, 89, 90, 573, 110, 385, 206, 148, 389, + /* 1340 */ 285, 587, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70, @@ -71064,17 +73217,17 @@ static const YYCODETYPE yy_lookahead[] = { /* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76, /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, /* 140 */ 44, 80, 81, 82, 83, 84, 23, 84, 169, 170, - /* 150 */ 19, 164, 165, 166, 23, 169, 60, 61, 62, 63, - /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 169, + /* 150 */ 19, 164, 165, 166, 23, 23, 60, 61, 62, 63, + /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 110, /* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 180 */ 84, 16, 14, 147, 150, 147, 21, 167, 168, 58, - /* 190 */ 211, 147, 156, 157, 23, 216, 176, 23, 181, 176, - /* 200 */ 177, 78, 79, 165, 166, 110, 183, 42, 43, 78, - /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 123, 88, - /* 220 */ 52, 98, 54, 92, 16, 60, 61, 62, 63, 64, + /* 180 */ 84, 16, 123, 147, 150, 147, 21, 167, 168, 58, + /* 190 */ 211, 147, 156, 157, 92, 216, 176, 23, 147, 176, + /* 200 */ 177, 78, 79, 165, 166, 103, 183, 42, 43, 78, + /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 169, 88, + /* 220 */ 88, 98, 99, 92, 16, 60, 61, 62, 63, 64, /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74, /* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 88, + /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 208, /* 260 */ 169, 170, 88, 89, 230, 227, 228, 16, 60, 61, /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81, @@ -71083,7 +73236,7 @@ static const YYCODETYPE yy_lookahead[] = { /* 310 */ 163, 60, 61, 62, 63, 64, 65, 66, 67, 68, /* 320 */ 69, 70, 71, 72, 161, 74, 75, 76, 77, 78, /* 330 */ 79, 80, 81, 82, 83, 84, 192, 200, 147, 131, - /* 340 */ 16, 200, 16, 199, 20, 190, 88, 89, 90, 185, + /* 340 */ 16, 200, 16, 199, 20, 169, 88, 89, 90, 185, /* 350 */ 186, 93, 94, 95, 217, 22, 219, 220, 147, 147, /* 360 */ 169, 170, 104, 200, 84, 147, 42, 43, 156, 157, /* 370 */ 90, 91, 92, 93, 94, 95, 96, 164, 165, 166, @@ -71093,14 +73246,14 @@ static const YYCODETYPE yy_lookahead[] = { /* 410 */ 84, 11, 221, 20, 30, 16, 147, 91, 92, 93, /* 420 */ 94, 95, 96, 90, 147, 181, 93, 94, 95, 103, /* 430 */ 212, 189, 155, 27, 50, 42, 43, 104, 169, 170, - /* 440 */ 34, 228, 43, 201, 202, 147, 169, 170, 206, 49, + /* 440 */ 34, 228, 43, 201, 202, 181, 169, 170, 206, 49, /* 450 */ 161, 162, 163, 60, 61, 62, 63, 64, 65, 66, /* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76, /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 25, /* 480 */ 211, 147, 20, 29, 12, 147, 102, 19, 211, 21, /* 490 */ 147, 141, 147, 216, 144, 41, 24, 98, 20, 99, /* 500 */ 100, 101, 103, 165, 42, 43, 0, 1, 2, 37, - /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 147, + /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 190, /* 520 */ 22, 49, 60, 61, 62, 63, 64, 65, 66, 67, /* 530 */ 68, 69, 70, 71, 72, 155, 74, 75, 76, 77, /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 147, 90, @@ -71109,14 +73262,14 @@ static const YYCODETYPE yy_lookahead[] = { /* 570 */ 169, 170, 16, 42, 43, 20, 19, 22, 19, 20, /* 580 */ 23, 22, 18, 147, 106, 147, 108, 109, 63, 64, /* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 600 */ 69, 70, 71, 72, 186, 74, 75, 76, 77, 78, + /* 600 */ 69, 70, 71, 72, 147, 74, 75, 76, 77, 78, /* 610 */ 79, 80, 81, 82, 83, 84, 16, 92, 59, 55, /* 620 */ 212, 21, 147, 19, 147, 23, 188, 23, 12, 217, - /* 630 */ 23, 219, 220, 7, 8, 9, 106, 147, 108, 109, + /* 630 */ 23, 219, 220, 7, 8, 9, 106, 186, 108, 109, /* 640 */ 24, 147, 42, 43, 208, 88, 89, 106, 92, 108, - /* 650 */ 109, 244, 245, 37, 145, 39, 191, 182, 94, 16, + /* 650 */ 109, 244, 245, 37, 147, 39, 147, 182, 94, 16, /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - /* 670 */ 70, 71, 72, 147, 74, 75, 76, 77, 78, 79, + /* 670 */ 70, 71, 72, 145, 74, 75, 76, 77, 78, 79, /* 680 */ 80, 81, 82, 83, 84, 42, 43, 80, 142, 143, /* 690 */ 88, 89, 88, 89, 148, 88, 89, 133, 14, 147, /* 700 */ 225, 155, 16, 60, 61, 62, 63, 64, 65, 66, @@ -71132,65 +73285,65 @@ static const YYCODETYPE yy_lookahead[] = { /* 800 */ 71, 72, 213, 74, 75, 76, 77, 78, 79, 80, /* 810 */ 81, 82, 83, 84, 42, 43, 23, 133, 225, 225, /* 820 */ 21, 225, 23, 189, 239, 236, 99, 100, 101, 22, - /* 830 */ 242, 243, 155, 22, 62, 63, 64, 65, 66, 67, + /* 830 */ 242, 243, 155, 191, 62, 63, 64, 65, 66, 67, /* 840 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77, - /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 43, + /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 22, /* 860 */ 19, 147, 147, 147, 23, 147, 189, 169, 170, 147, - /* 870 */ 147, 147, 31, 16, 17, 147, 19, 147, 124, 125, + /* 870 */ 14, 147, 31, 16, 17, 147, 19, 147, 19, 43, /* 880 */ 23, 88, 89, 169, 170, 169, 170, 88, 31, 48, /* 890 */ 147, 169, 170, 169, 170, 147, 89, 169, 170, 58, - /* 900 */ 147, 22, 147, 188, 147, 48, 188, 114, 97, 147, - /* 910 */ 147, 188, 147, 19, 98, 58, 147, 169, 170, 78, + /* 900 */ 147, 147, 147, 188, 147, 48, 188, 114, 52, 147, + /* 910 */ 54, 19, 147, 124, 125, 58, 147, 169, 170, 78, /* 920 */ 79, 114, 169, 170, 169, 170, 169, 170, 87, 88, - /* 930 */ 89, 169, 170, 92, 161, 78, 79, 80, 169, 170, - /* 940 */ 91, 147, 155, 22, 87, 88, 89, 16, 17, 92, - /* 950 */ 19, 110, 147, 155, 23, 147, 7, 8, 20, 110, - /* 960 */ 22, 80, 31, 169, 170, 124, 125, 126, 127, 128, - /* 970 */ 129, 208, 123, 208, 169, 170, 189, 169, 170, 48, - /* 980 */ 147, 124, 125, 126, 127, 128, 129, 189, 107, 58, - /* 990 */ 107, 5, 111, 147, 111, 203, 10, 11, 12, 13, - /* 1000 */ 121, 147, 147, 91, 92, 147, 112, 147, 147, 78, + /* 930 */ 89, 169, 170, 92, 98, 78, 79, 80, 169, 170, + /* 940 */ 91, 147, 188, 22, 87, 88, 89, 16, 17, 92, + /* 950 */ 19, 110, 147, 155, 23, 147, 155, 22, 121, 110, + /* 960 */ 68, 80, 31, 169, 170, 124, 125, 126, 127, 128, + /* 970 */ 129, 112, 123, 208, 169, 170, 107, 169, 170, 48, + /* 980 */ 111, 124, 125, 126, 127, 128, 129, 189, 107, 58, + /* 990 */ 189, 5, 111, 147, 7, 8, 10, 11, 12, 13, + /* 1000 */ 161, 20, 147, 22, 178, 147, 91, 92, 147, 78, /* 1010 */ 79, 147, 26, 19, 28, 169, 170, 23, 87, 88, - /* 1020 */ 89, 35, 147, 92, 169, 170, 178, 169, 170, 147, - /* 1030 */ 169, 170, 147, 47, 113, 49, 92, 178, 147, 53, - /* 1040 */ 147, 178, 56, 147, 169, 170, 147, 103, 147, 19, + /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 147, + /* 1030 */ 169, 170, 97, 47, 113, 49, 20, 203, 22, 53, + /* 1040 */ 147, 147, 56, 147, 169, 170, 147, 147, 147, 20, /* 1050 */ 147, 169, 170, 147, 147, 124, 125, 126, 127, 128, - /* 1060 */ 129, 147, 169, 170, 147, 169, 170, 147, 169, 170, + /* 1060 */ 129, 147, 169, 170, 178, 169, 170, 147, 169, 170, /* 1070 */ 169, 170, 169, 170, 147, 169, 170, 147, 20, 147, - /* 1080 */ 22, 147, 88, 147, 232, 99, 100, 101, 147, 169, - /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 147, 68, 169, + /* 1080 */ 22, 147, 88, 147, 147, 99, 100, 101, 59, 169, + /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 178, 147, 169, /* 1100 */ 170, 169, 170, 169, 170, 169, 170, 20, 147, 22, - /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 20, - /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 147, 20, 147, - /* 1130 */ 22, 233, 169, 170, 169, 170, 20, 147, 22, 147, + /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 147, + /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 147, 20, 232, + /* 1130 */ 22, 233, 169, 170, 169, 170, 147, 147, 147, 147, /* 1140 */ 169, 170, 147, 147, 169, 170, 147, 169, 170, 169, - /* 1150 */ 170, 147, 147, 147, 147, 191, 172, 149, 59, 193, - /* 1160 */ 223, 161, 229, 172, 229, 172, 177, 194, 194, 172, - /* 1170 */ 161, 161, 6, 172, 146, 173, 22, 146, 146, 146, - /* 1180 */ 154, 121, 194, 118, 116, 119, 130, 189, 112, 120, - /* 1190 */ 222, 152, 152, 98, 115, 98, 171, 40, 195, 179, - /* 1200 */ 171, 19, 97, 84, 15, 171, 179, 196, 173, 197, - /* 1210 */ 174, 198, 171, 226, 171, 171, 171, 38, 204, 152, - /* 1220 */ 205, 204, 174, 205, 152, 151, 151, 60, 151, 19, - /* 1230 */ 152, 184, 152, 130, 151, 184, 152, 214, 152, 15, - /* 1240 */ 194, 187, 226, 194, 187, 152, 187, 184, 187, 33, - /* 1250 */ 152, 214, 152, 234, 137, 159, 235, 175, 1, 237, - /* 1260 */ 175, 237, 20, 112, 112, 112, 92, 112, 107, 19, - /* 1270 */ 11, 20, 20, 231, 19, 19, 22, 117, 240, 117, - /* 1280 */ 20, 20, 20, 114, 19, 22, 22, 20, 112, 20, - /* 1290 */ 20, 44, 19, 243, 19, 96, 20, 44, 246, 19, - /* 1300 */ 32, 19, 44, 19, 103, 16, 21, 17, 36, 98, - /* 1310 */ 22, 133, 98, 19, 5, 1, 45, 51, 122, 45, - /* 1320 */ 102, 19, 113, 115, 14, 17, 113, 102, 122, 14, - /* 1330 */ 19, 136, 20, 135, 3, 123, 57, 19, 4, 247, - /* 1340 */ 247, 247, 247, 247, 247, 68, 68, + /* 1150 */ 170, 147, 147, 147, 147, 147, 147, 191, 161, 149, + /* 1160 */ 193, 177, 229, 223, 161, 172, 6, 229, 194, 146, + /* 1170 */ 172, 194, 172, 172, 172, 161, 146, 146, 146, 22, + /* 1180 */ 154, 121, 194, 118, 173, 119, 116, 120, 112, 130, + /* 1190 */ 222, 152, 152, 98, 115, 98, 171, 97, 171, 40, + /* 1200 */ 179, 189, 19, 84, 171, 226, 171, 173, 195, 226, + /* 1210 */ 174, 196, 171, 171, 197, 171, 198, 179, 15, 174, + /* 1220 */ 151, 60, 151, 204, 152, 205, 204, 152, 151, 205, + /* 1230 */ 152, 38, 152, 130, 151, 184, 152, 184, 19, 15, + /* 1240 */ 194, 152, 187, 187, 187, 152, 194, 184, 187, 33, + /* 1250 */ 152, 152, 137, 159, 1, 20, 175, 214, 112, 112, + /* 1260 */ 175, 214, 234, 112, 112, 92, 19, 11, 20, 107, + /* 1270 */ 20, 19, 235, 19, 32, 20, 112, 114, 20, 22, + /* 1280 */ 20, 22, 117, 22, 117, 237, 237, 19, 44, 20, + /* 1290 */ 240, 20, 20, 231, 19, 44, 19, 243, 20, 19, + /* 1300 */ 19, 19, 96, 103, 16, 21, 44, 17, 98, 36, + /* 1310 */ 246, 45, 45, 22, 51, 133, 98, 19, 5, 1, + /* 1320 */ 122, 19, 102, 14, 113, 17, 113, 115, 102, 122, + /* 1330 */ 19, 123, 68, 68, 20, 14, 57, 135, 19, 3, + /* 1340 */ 136, 4, }; #define YY_SHIFT_USE_DFLT (-62) #define YY_SHIFT_MAX 389 static const short yy_shift_ofst[] = { /* 0 */ 39, 841, 986, -16, 841, 931, 931, 258, 123, -36, /* 10 */ 96, 931, 931, 931, 931, 931, -45, 400, 174, 19, - /* 20 */ 171, -54, -54, 53, 165, 208, 251, 324, 393, 462, + /* 20 */ 132, -54, -54, 53, 165, 208, 251, 324, 393, 462, /* 30 */ 531, 600, 643, 686, 643, 643, 643, 643, 643, 643, /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931, @@ -71199,34 +73352,34 @@ static const short yy_shift_ofst[] = { /* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, /* 90 */ 931, 931, 931, 931, 931, 931, -61, -61, 6, 6, /* 100 */ 280, 22, 61, 399, 564, 19, 19, 19, 19, 19, - /* 110 */ 19, 19, 216, 171, 63, -62, -62, -62, 131, 326, + /* 110 */ 19, 19, 216, 132, 63, -62, -62, -62, 131, 326, /* 120 */ 472, 472, 498, 559, 506, 799, 19, 799, 19, 19, /* 130 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - /* 140 */ 19, 849, 95, -36, -36, -36, -62, -62, -62, -15, + /* 140 */ 19, 849, 59, -36, -36, -36, -62, -62, -62, -15, /* 150 */ -15, 333, 459, 478, 557, 530, 541, 616, 602, 793, /* 160 */ 604, 607, 626, 19, 19, 881, 19, 19, 994, 19, /* 170 */ 19, 807, 19, 19, 673, 807, 19, 19, 384, 384, /* 180 */ 384, 19, 19, 673, 19, 19, 673, 19, 454, 685, /* 190 */ 19, 19, 673, 19, 19, 19, 673, 19, 19, 19, - /* 200 */ 673, 673, 19, 19, 19, 19, 19, 468, 883, 921, - /* 210 */ 171, 754, 754, 432, 406, 406, 406, 816, 406, 171, - /* 220 */ 406, 171, 811, 879, 879, 1166, 1166, 1166, 1166, 1154, - /* 230 */ -36, 1060, 1065, 1066, 1068, 1069, 1056, 1076, 1076, 1095, - /* 240 */ 1079, 1095, 1079, 1097, 1097, 1157, 1097, 1105, 1097, 1182, - /* 250 */ 1119, 1119, 1157, 1097, 1097, 1097, 1182, 1189, 1076, 1189, - /* 260 */ 1076, 1189, 1076, 1076, 1179, 1103, 1189, 1076, 1167, 1167, - /* 270 */ 1210, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1167, 1210, - /* 280 */ 1076, 1216, 1216, 1076, 1076, 1117, -62, -62, -62, -62, - /* 290 */ -62, -62, 525, 684, 727, 168, 894, 556, 555, 938, - /* 300 */ 944, 949, 912, 1058, 1073, 1087, 1091, 1101, 1104, 1108, - /* 310 */ 1030, 1116, 1099, 1257, 1242, 1151, 1152, 1153, 1155, 1174, - /* 320 */ 1161, 1250, 1251, 1252, 1255, 1259, 1256, 1260, 1254, 1261, - /* 330 */ 1262, 1263, 1160, 1264, 1162, 1263, 1169, 1265, 1267, 1176, - /* 340 */ 1269, 1270, 1268, 1247, 1273, 1253, 1275, 1276, 1280, 1282, - /* 350 */ 1258, 1284, 1199, 1201, 1289, 1290, 1285, 1211, 1272, 1266, - /* 360 */ 1271, 1288, 1274, 1178, 1214, 1294, 1309, 1314, 1218, 1277, - /* 370 */ 1278, 1196, 1302, 1209, 1310, 1208, 1308, 1213, 1225, 1206, - /* 380 */ 1311, 1212, 1312, 1315, 1279, 1198, 1195, 1318, 1331, 1334, + /* 200 */ 673, 673, 19, 19, 19, 19, 19, 468, 869, 921, + /* 210 */ 132, 789, 789, 432, 406, 406, 406, 836, 406, 132, + /* 220 */ 406, 132, 935, 837, 837, 1160, 1160, 1160, 1160, 1157, + /* 230 */ -36, 1060, 1065, 1066, 1070, 1067, 1059, 1076, 1076, 1095, + /* 240 */ 1079, 1095, 1079, 1097, 1097, 1159, 1097, 1100, 1097, 1183, + /* 250 */ 1119, 1119, 1159, 1097, 1097, 1097, 1183, 1203, 1076, 1203, + /* 260 */ 1076, 1203, 1076, 1076, 1193, 1103, 1203, 1076, 1161, 1161, + /* 270 */ 1219, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1161, 1219, + /* 280 */ 1076, 1216, 1216, 1076, 1076, 1115, -62, -62, -62, -62, + /* 290 */ -62, -62, 525, 684, 727, 856, 859, 556, 555, 981, + /* 300 */ 102, 987, 915, 1016, 1058, 1073, 1087, 1091, 1101, 1104, + /* 310 */ 892, 1108, 1029, 1253, 1235, 1146, 1147, 1151, 1152, 1173, + /* 320 */ 1162, 1247, 1248, 1250, 1252, 1256, 1254, 1255, 1257, 1258, + /* 330 */ 1260, 1259, 1165, 1261, 1167, 1259, 1163, 1268, 1269, 1164, + /* 340 */ 1271, 1272, 1242, 1244, 1275, 1251, 1277, 1278, 1280, 1281, + /* 350 */ 1262, 1282, 1206, 1200, 1288, 1290, 1284, 1210, 1273, 1263, + /* 360 */ 1266, 1291, 1267, 1182, 1218, 1298, 1313, 1318, 1220, 1264, + /* 370 */ 1265, 1198, 1302, 1211, 1309, 1212, 1308, 1213, 1226, 1207, + /* 380 */ 1311, 1208, 1314, 1321, 1279, 1202, 1204, 1319, 1336, 1337, }; #define YY_REDUCE_USE_DFLT (-165) #define YY_REDUCE_MAX 291 @@ -71243,85 +73396,85 @@ static const short yy_reduce_ofst[] = { /* 90 */ 963, 965, 971, 975, 978, 980, 412, 412, 412, 412, /* 100 */ 20, 412, 412, 23, 34, 334, 475, 552, 593, 594, /* 110 */ 585, 212, 412, 289, 412, 412, 412, 412, 135, -164, - /* 120 */ -115, 164, 407, 407, 350, 141, 436, 163, 596, -90, - /* 130 */ 763, 218, 765, 438, 586, 592, 595, 715, 718, 408, - /* 140 */ 723, 380, 634, 677, 787, 798, 144, 529, 588, -14, - /* 150 */ 0, 17, 244, 155, 298, 155, 155, 418, 372, 477, - /* 160 */ 490, 494, 509, 526, 590, 465, 494, 730, 773, 743, - /* 170 */ 833, 792, 854, 860, 155, 792, 864, 885, 848, 859, - /* 180 */ 863, 891, 907, 155, 914, 917, 155, 927, 852, 898, - /* 190 */ 941, 950, 155, 961, 982, 990, 155, 992, 995, 996, - /* 200 */ 155, 155, 999, 1004, 1005, 1006, 1007, 1008, 964, 966, - /* 210 */ 1000, 933, 935, 937, 984, 991, 993, 989, 997, 1009, - /* 220 */ 1001, 1010, 1002, 973, 974, 1028, 1031, 1032, 1033, 1026, - /* 230 */ 998, 988, 1003, 1011, 1012, 1013, 968, 1039, 1040, 1014, - /* 240 */ 1015, 1017, 1018, 1025, 1029, 1020, 1034, 1035, 1041, 1036, - /* 250 */ 987, 1016, 1027, 1043, 1044, 1045, 1048, 1074, 1067, 1075, - /* 260 */ 1072, 1077, 1078, 1080, 1019, 1021, 1083, 1084, 1047, 1051, - /* 270 */ 1023, 1046, 1086, 1054, 1057, 1059, 1061, 1049, 1063, 1037, - /* 280 */ 1093, 1022, 1024, 1098, 1100, 1038, 1096, 1082, 1085, 1042, - /* 290 */ 1050, 1052, + /* 120 */ -115, 164, 407, 407, 350, 141, 51, 163, 596, -90, + /* 130 */ 436, 218, 765, 438, 586, 592, 595, 715, 718, 408, + /* 140 */ 754, 380, 634, 677, 798, 801, 144, 529, 588, 49, + /* 150 */ 176, 244, 264, 329, 457, 329, 329, 451, 477, 494, + /* 160 */ 507, 509, 528, 590, 730, 642, 509, 743, 839, 864, + /* 170 */ 879, 834, 894, 900, 329, 834, 907, 914, 826, 886, + /* 180 */ 919, 927, 937, 329, 951, 961, 329, 972, 897, 898, + /* 190 */ 989, 990, 329, 991, 992, 995, 329, 996, 999, 1004, + /* 200 */ 329, 329, 1005, 1006, 1007, 1008, 1009, 1010, 966, 967, + /* 210 */ 997, 933, 938, 940, 993, 998, 1000, 984, 1001, 1003, + /* 220 */ 1002, 1014, 1011, 974, 977, 1023, 1030, 1031, 1032, 1026, + /* 230 */ 1012, 988, 1013, 1015, 1017, 1018, 968, 1039, 1040, 1019, + /* 240 */ 1020, 1022, 1024, 1025, 1027, 1021, 1033, 1034, 1035, 1036, + /* 250 */ 979, 983, 1038, 1041, 1042, 1044, 1045, 1069, 1072, 1071, + /* 260 */ 1075, 1077, 1078, 1080, 1028, 1037, 1083, 1084, 1051, 1053, + /* 270 */ 1043, 1046, 1089, 1055, 1056, 1057, 1061, 1052, 1063, 1047, + /* 280 */ 1093, 1048, 1049, 1098, 1099, 1050, 1094, 1081, 1085, 1062, + /* 290 */ 1054, 1064, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 594, 819, 900, 709, 900, 819, 900, 900, 846, 713, - /* 10 */ 875, 817, 900, 900, 900, 900, 791, 900, 846, 900, - /* 20 */ 625, 846, 846, 742, 900, 900, 900, 900, 900, 900, - /* 30 */ 900, 900, 743, 900, 821, 816, 812, 814, 813, 820, - /* 40 */ 744, 733, 740, 747, 725, 859, 749, 750, 756, 757, - /* 50 */ 876, 874, 779, 778, 797, 900, 900, 900, 900, 900, - /* 60 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 70 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 80 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 90 */ 900, 900, 900, 900, 900, 900, 781, 803, 780, 790, - /* 100 */ 618, 782, 783, 678, 613, 900, 900, 900, 900, 900, - /* 110 */ 900, 900, 784, 900, 785, 798, 799, 800, 900, 900, - /* 120 */ 900, 900, 900, 900, 594, 709, 900, 709, 900, 900, - /* 130 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 140 */ 900, 900, 900, 900, 900, 900, 703, 713, 893, 900, - /* 150 */ 900, 669, 900, 900, 900, 900, 900, 900, 900, 900, - /* 160 */ 900, 900, 601, 599, 900, 701, 900, 900, 627, 900, - /* 170 */ 900, 711, 900, 900, 716, 717, 900, 900, 900, 900, - /* 180 */ 900, 900, 900, 615, 900, 900, 690, 900, 852, 900, - /* 190 */ 900, 900, 866, 900, 900, 900, 864, 900, 900, 900, - /* 200 */ 692, 752, 833, 900, 879, 881, 900, 900, 701, 710, - /* 210 */ 900, 900, 900, 815, 736, 736, 736, 648, 736, 900, - /* 220 */ 736, 900, 651, 746, 746, 598, 598, 598, 598, 668, - /* 230 */ 900, 746, 737, 739, 729, 741, 900, 718, 718, 726, - /* 240 */ 728, 726, 728, 680, 680, 665, 680, 651, 680, 825, - /* 250 */ 830, 830, 665, 680, 680, 680, 825, 610, 718, 610, - /* 260 */ 718, 610, 718, 718, 856, 858, 610, 718, 682, 682, - /* 270 */ 758, 746, 718, 689, 689, 689, 689, 746, 682, 758, - /* 280 */ 718, 878, 878, 718, 718, 886, 635, 653, 653, 861, - /* 290 */ 893, 898, 900, 900, 900, 900, 765, 900, 900, 900, - /* 300 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 310 */ 839, 900, 900, 900, 900, 770, 766, 900, 767, 900, - /* 320 */ 695, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 330 */ 900, 818, 900, 730, 900, 738, 900, 900, 900, 900, - /* 340 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 350 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 360 */ 854, 855, 900, 900, 900, 900, 900, 900, 900, 900, - /* 370 */ 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - /* 380 */ 900, 900, 900, 900, 885, 900, 900, 888, 595, 900, - /* 390 */ 589, 592, 591, 593, 597, 600, 622, 623, 624, 602, - /* 400 */ 603, 604, 605, 606, 607, 608, 614, 616, 634, 636, - /* 410 */ 620, 638, 699, 700, 762, 693, 694, 698, 621, 773, - /* 420 */ 764, 768, 769, 771, 772, 786, 787, 789, 795, 802, - /* 430 */ 805, 788, 793, 794, 796, 801, 804, 696, 697, 808, - /* 440 */ 628, 629, 632, 633, 842, 844, 843, 845, 631, 630, - /* 450 */ 774, 777, 810, 811, 867, 868, 869, 870, 871, 806, - /* 460 */ 719, 809, 792, 731, 734, 735, 732, 702, 712, 721, - /* 470 */ 722, 723, 724, 707, 708, 714, 727, 760, 761, 715, - /* 480 */ 704, 705, 706, 807, 763, 775, 776, 639, 640, 770, - /* 490 */ 641, 642, 643, 681, 684, 685, 686, 644, 663, 666, - /* 500 */ 667, 645, 652, 646, 647, 654, 655, 656, 659, 660, - /* 510 */ 661, 662, 657, 658, 826, 827, 831, 829, 828, 649, - /* 520 */ 650, 664, 637, 626, 619, 670, 673, 674, 675, 676, - /* 530 */ 677, 679, 671, 672, 617, 609, 611, 720, 848, 857, - /* 540 */ 853, 849, 850, 851, 612, 822, 823, 683, 754, 755, - /* 550 */ 847, 860, 862, 759, 863, 865, 890, 687, 688, 691, - /* 560 */ 832, 872, 745, 748, 751, 753, 834, 835, 836, 837, - /* 570 */ 840, 841, 838, 873, 877, 880, 882, 883, 884, 887, - /* 580 */ 889, 894, 895, 896, 899, 897, 596, 590, + /* 0 */ 595, 820, 902, 710, 902, 820, 902, 902, 848, 714, + /* 10 */ 877, 818, 902, 902, 902, 902, 792, 902, 848, 902, + /* 20 */ 626, 848, 848, 743, 902, 902, 902, 902, 902, 902, + /* 30 */ 902, 902, 744, 902, 822, 817, 813, 815, 814, 821, + /* 40 */ 745, 734, 741, 748, 726, 861, 750, 751, 757, 758, + /* 50 */ 878, 876, 780, 779, 798, 902, 902, 902, 902, 902, + /* 60 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 70 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 80 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 90 */ 902, 902, 902, 902, 902, 902, 782, 804, 781, 791, + /* 100 */ 619, 783, 784, 679, 614, 902, 902, 902, 902, 902, + /* 110 */ 902, 902, 785, 902, 786, 799, 800, 801, 902, 902, + /* 120 */ 902, 902, 902, 902, 595, 710, 902, 710, 902, 902, + /* 130 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 140 */ 902, 902, 902, 902, 902, 902, 704, 714, 895, 902, + /* 150 */ 902, 670, 902, 902, 902, 902, 902, 902, 902, 902, + /* 160 */ 902, 902, 602, 600, 902, 702, 902, 902, 628, 902, + /* 170 */ 902, 712, 902, 902, 717, 718, 902, 902, 902, 902, + /* 180 */ 902, 902, 902, 616, 902, 902, 691, 902, 854, 902, + /* 190 */ 902, 902, 868, 902, 902, 902, 866, 902, 902, 902, + /* 200 */ 693, 753, 834, 902, 881, 883, 902, 902, 702, 711, + /* 210 */ 902, 902, 902, 816, 737, 737, 737, 649, 737, 902, + /* 220 */ 737, 902, 652, 747, 747, 599, 599, 599, 599, 669, + /* 230 */ 902, 747, 738, 740, 730, 742, 902, 719, 719, 727, + /* 240 */ 729, 727, 729, 681, 681, 666, 681, 652, 681, 826, + /* 250 */ 831, 831, 666, 681, 681, 681, 826, 611, 719, 611, + /* 260 */ 719, 611, 719, 719, 858, 860, 611, 719, 683, 683, + /* 270 */ 759, 747, 719, 690, 690, 690, 690, 747, 683, 759, + /* 280 */ 719, 880, 880, 719, 719, 888, 636, 654, 654, 863, + /* 290 */ 895, 900, 902, 902, 902, 902, 766, 902, 902, 902, + /* 300 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 310 */ 841, 902, 902, 902, 902, 771, 767, 902, 768, 902, + /* 320 */ 696, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 330 */ 902, 819, 902, 731, 902, 739, 902, 902, 902, 902, + /* 340 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 350 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 360 */ 856, 857, 902, 902, 902, 902, 902, 902, 902, 902, + /* 370 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + /* 380 */ 902, 902, 902, 902, 887, 902, 902, 890, 596, 902, + /* 390 */ 590, 593, 592, 594, 598, 601, 623, 624, 625, 603, + /* 400 */ 604, 605, 606, 607, 608, 609, 615, 617, 635, 637, + /* 410 */ 621, 639, 700, 701, 763, 694, 695, 699, 622, 774, + /* 420 */ 765, 769, 770, 772, 773, 787, 788, 790, 796, 803, + /* 430 */ 806, 789, 794, 795, 797, 802, 805, 697, 698, 809, + /* 440 */ 629, 630, 633, 634, 844, 846, 845, 847, 632, 631, + /* 450 */ 775, 778, 811, 812, 869, 870, 871, 872, 873, 807, + /* 460 */ 720, 810, 793, 732, 735, 736, 733, 703, 713, 722, + /* 470 */ 723, 724, 725, 708, 709, 715, 728, 761, 762, 716, + /* 480 */ 705, 706, 707, 808, 764, 776, 777, 640, 641, 771, + /* 490 */ 642, 643, 644, 682, 685, 686, 687, 645, 664, 667, + /* 500 */ 668, 646, 653, 647, 648, 655, 656, 657, 660, 661, + /* 510 */ 662, 663, 658, 659, 827, 828, 832, 830, 829, 650, + /* 520 */ 651, 665, 638, 627, 620, 671, 674, 675, 676, 677, + /* 530 */ 678, 680, 672, 673, 618, 610, 612, 721, 850, 859, + /* 540 */ 855, 851, 852, 853, 613, 823, 824, 684, 755, 756, + /* 550 */ 849, 862, 864, 760, 865, 867, 892, 688, 689, 692, + /* 560 */ 833, 874, 746, 749, 752, 754, 835, 836, 837, 838, + /* 570 */ 839, 842, 843, 840, 875, 879, 882, 884, 885, 886, + /* 580 */ 889, 891, 896, 897, 898, 901, 899, 597, 591, }; #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) @@ -71867,69 +74020,70 @@ static const char *const yyRuleName[] = { /* 246 */ "cmd ::= VACUUM nm", /* 247 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", /* 248 */ "cmd ::= PRAGMA nm dbnm EQ ON", - /* 249 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 250 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 251 */ "cmd ::= PRAGMA nm dbnm", - /* 252 */ "nmnum ::= plus_num", - /* 253 */ "nmnum ::= nm", - /* 254 */ "plus_num ::= plus_opt number", - /* 255 */ "minus_num ::= MINUS number", - /* 256 */ "number ::= INTEGER|FLOAT", - /* 257 */ "plus_opt ::= PLUS", - /* 258 */ "plus_opt ::=", - /* 259 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", - /* 260 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 261 */ "trigger_time ::= BEFORE", - /* 262 */ "trigger_time ::= AFTER", - /* 263 */ "trigger_time ::= INSTEAD OF", - /* 264 */ "trigger_time ::=", - /* 265 */ "trigger_event ::= DELETE|INSERT", - /* 266 */ "trigger_event ::= UPDATE", - /* 267 */ "trigger_event ::= UPDATE OF inscollist", - /* 268 */ "foreach_clause ::=", - /* 269 */ "foreach_clause ::= FOR EACH ROW", - /* 270 */ "when_clause ::=", - /* 271 */ "when_clause ::= WHEN expr", - /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 273 */ "trigger_cmd_list ::=", - /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", - /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", - /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", - /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt", - /* 278 */ "trigger_cmd ::= select", - /* 279 */ "expr ::= RAISE LP IGNORE RP", - /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 281 */ "raisetype ::= ROLLBACK", - /* 282 */ "raisetype ::= ABORT", - /* 283 */ "raisetype ::= FAIL", - /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 286 */ "cmd ::= DETACH database_kw_opt expr", - /* 287 */ "key_opt ::=", - /* 288 */ "key_opt ::= KEY expr", - /* 289 */ "database_kw_opt ::= DATABASE", - /* 290 */ "database_kw_opt ::=", - /* 291 */ "cmd ::= REINDEX", - /* 292 */ "cmd ::= REINDEX nm dbnm", - /* 293 */ "cmd ::= ANALYZE", - /* 294 */ "cmd ::= ANALYZE nm dbnm", - /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 297 */ "add_column_fullname ::= fullname", - /* 298 */ "kwcolumn_opt ::=", - /* 299 */ "kwcolumn_opt ::= COLUMNKW", - /* 300 */ "cmd ::= create_vtab", - /* 301 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", - /* 303 */ "vtabarglist ::= vtabarg", - /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 305 */ "vtabarg ::=", - /* 306 */ "vtabarg ::= vtabarg vtabargtoken", - /* 307 */ "vtabargtoken ::= ANY", - /* 308 */ "vtabargtoken ::= lp anylist RP", - /* 309 */ "lp ::= LP", - /* 310 */ "anylist ::=", - /* 311 */ "anylist ::= anylist ANY", + /* 249 */ "cmd ::= PRAGMA nm dbnm EQ DELETE", + /* 250 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 251 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 252 */ "cmd ::= PRAGMA nm dbnm", + /* 253 */ "nmnum ::= plus_num", + /* 254 */ "nmnum ::= nm", + /* 255 */ "plus_num ::= plus_opt number", + /* 256 */ "minus_num ::= MINUS number", + /* 257 */ "number ::= INTEGER|FLOAT", + /* 258 */ "plus_opt ::= PLUS", + /* 259 */ "plus_opt ::=", + /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", + /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 262 */ "trigger_time ::= BEFORE", + /* 263 */ "trigger_time ::= AFTER", + /* 264 */ "trigger_time ::= INSTEAD OF", + /* 265 */ "trigger_time ::=", + /* 266 */ "trigger_event ::= DELETE|INSERT", + /* 267 */ "trigger_event ::= UPDATE", + /* 268 */ "trigger_event ::= UPDATE OF inscollist", + /* 269 */ "foreach_clause ::=", + /* 270 */ "foreach_clause ::= FOR EACH ROW", + /* 271 */ "when_clause ::=", + /* 272 */ "when_clause ::= WHEN expr", + /* 273 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 274 */ "trigger_cmd_list ::=", + /* 275 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", + /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", + /* 277 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", + /* 278 */ "trigger_cmd ::= DELETE FROM nm where_opt", + /* 279 */ "trigger_cmd ::= select", + /* 280 */ "expr ::= RAISE LP IGNORE RP", + /* 281 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 282 */ "raisetype ::= ROLLBACK", + /* 283 */ "raisetype ::= ABORT", + /* 284 */ "raisetype ::= FAIL", + /* 285 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 286 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 287 */ "cmd ::= DETACH database_kw_opt expr", + /* 288 */ "key_opt ::=", + /* 289 */ "key_opt ::= KEY expr", + /* 290 */ "database_kw_opt ::= DATABASE", + /* 291 */ "database_kw_opt ::=", + /* 292 */ "cmd ::= REINDEX", + /* 293 */ "cmd ::= REINDEX nm dbnm", + /* 294 */ "cmd ::= ANALYZE", + /* 295 */ "cmd ::= ANALYZE nm dbnm", + /* 296 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 297 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 298 */ "add_column_fullname ::= fullname", + /* 299 */ "kwcolumn_opt ::=", + /* 300 */ "kwcolumn_opt ::= COLUMNKW", + /* 301 */ "cmd ::= create_vtab", + /* 302 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 303 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", + /* 304 */ "vtabarglist ::= vtabarg", + /* 305 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 306 */ "vtabarg ::=", + /* 307 */ "vtabarg ::= vtabarg vtabargtoken", + /* 308 */ "vtabargtoken ::= ANY", + /* 309 */ "vtabargtoken ::= lp anylist RP", + /* 310 */ "lp ::= LP", + /* 311 */ "anylist ::=", + /* 312 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ @@ -71999,54 +74153,184 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ ** inside the C code. */ case 155: /* select */ - case 189: /* oneselect */ - case 206: /* seltablist_paren */ -{sqlite3SelectDelete((yypminor->yy219));} +{ +sqlite3SelectDelete((yypminor->yy219)); +} break; case 169: /* term */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; case 170: /* expr */ - case 194: /* where_opt */ - case 196: /* having_opt */ - case 204: /* on_opt */ - case 210: /* sortitem */ - case 218: /* escape */ - case 221: /* case_operand */ - case 223: /* case_else */ - case 235: /* when_clause */ - case 238: /* key_opt */ -{sqlite3ExprDelete((yypminor->yy172));} +{ +sqlite3ExprDelete((yypminor->yy172)); +} break; case 174: /* idxlist_opt */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; case 182: /* idxlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 188: /* fullname */ +{ +sqlite3SrcListDelete((yypminor->yy373)); +} + break; + case 189: /* oneselect */ +{ +sqlite3SelectDelete((yypminor->yy219)); +} + break; case 192: /* selcollist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 193: /* from */ +{ +sqlite3SrcListDelete((yypminor->yy373)); +} + break; + case 194: /* where_opt */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; case 195: /* groupby_opt */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 196: /* having_opt */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; case 197: /* orderby_opt */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; case 199: /* sclp */ - case 209: /* sortlist */ - case 211: /* nexprlist */ - case 212: /* setlist */ - case 215: /* itemlist */ - case 216: /* exprlist */ - case 222: /* case_exprlist */ -{sqlite3ExprListDelete((yypminor->yy174));} +{ +sqlite3ExprListDelete((yypminor->yy174)); +} break; - case 188: /* fullname */ - case 193: /* from */ case 201: /* seltablist */ +{ +sqlite3SrcListDelete((yypminor->yy373)); +} + break; case 202: /* stl_prefix */ -{sqlite3SrcListDelete((yypminor->yy373));} +{ +sqlite3SrcListDelete((yypminor->yy373)); +} + break; + case 204: /* on_opt */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} break; case 205: /* using_opt */ +{ +sqlite3IdListDelete((yypminor->yy432)); +} + break; + case 206: /* seltablist_paren */ +{ +sqlite3SelectDelete((yypminor->yy219)); +} + break; case 208: /* inscollist */ +{ +sqlite3IdListDelete((yypminor->yy432)); +} + break; + case 209: /* sortlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 210: /* sortitem */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; + case 211: /* nexprlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 212: /* setlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; case 214: /* inscollist_opt */ -{sqlite3IdListDelete((yypminor->yy432));} +{ +sqlite3IdListDelete((yypminor->yy432)); +} + break; + case 215: /* itemlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 216: /* exprlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 218: /* escape */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; + case 221: /* case_operand */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; + case 222: /* case_exprlist */ +{ +sqlite3ExprListDelete((yypminor->yy174)); +} + break; + case 223: /* case_else */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} break; case 231: /* trigger_cmd_list */ - case 236: /* trigger_cmd */ -{sqlite3DeleteTriggerStep((yypminor->yy243));} +{ +sqlite3DeleteTriggerStep((yypminor->yy243)); +} break; case 233: /* trigger_event */ -{sqlite3IdListDelete((yypminor->yy370).b);} +{ +sqlite3IdListDelete((yypminor->yy370).b); +} + break; + case 235: /* when_clause */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} + break; + case 236: /* trigger_cmd */ +{ +sqlite3DeleteTriggerStep((yypminor->yy243)); +} + break; + case 238: /* key_opt */ +{ +sqlite3ExprDelete((yypminor->yy172)); +} break; default: break; /* If no destructor action specified: do nothing */ } @@ -72172,13 +74456,25 @@ static int yy_find_reduce_action( YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; +#ifdef YYERRORSYMBOL + if( stateno>YY_REDUCE_MAX ){ + return yy_default[stateno]; + } +#else assert( stateno<=YY_REDUCE_MAX ); +#endif i = yy_reduce_ofst[stateno]; assert( i!=YY_REDUCE_USE_DFLT ); assert( iLookAhead!=YYNOCODE ); i += iLookAhead; +#ifdef YYERRORSYMBOL + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ + return yy_default[stateno]; + } +#else assert( i>=0 && ia[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } break; @@ -73405,7 +75703,7 @@ static void yy_reduce( sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy410); } yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy410); - sqlite3ExprListCheckLength(pParse, yygotominor.yy174, SQLITE_MAX_COLUMN, "index"); + sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index"); if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; } break; @@ -73423,20 +75721,21 @@ static void yy_reduce( {sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,0);} break; case 248: /* cmd ::= PRAGMA nm dbnm EQ ON */ + case 249: /* cmd ::= PRAGMA nm dbnm EQ DELETE */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy0,0);} break; - case 249: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 250: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ { sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,1); } break; - case 250: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 251: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-1].minor.yy410,0);} break; - case 251: /* cmd ::= PRAGMA nm dbnm */ + case 252: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,0,0);} break; - case 259: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */ + case 260: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy410.z; @@ -73444,38 +75743,38 @@ static void yy_reduce( sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all); } break; - case 260: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy410, &yymsp[-6].minor.yy410, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46); yygotominor.yy410 = (yymsp[-6].minor.yy410.n==0?yymsp[-7].minor.yy410:yymsp[-6].minor.yy410); } break; - case 261: /* trigger_time ::= BEFORE */ - case 264: /* trigger_time ::= */ + case 262: /* trigger_time ::= BEFORE */ + case 265: /* trigger_time ::= */ { yygotominor.yy46 = TK_BEFORE; } break; - case 262: /* trigger_time ::= AFTER */ + case 263: /* trigger_time ::= AFTER */ { yygotominor.yy46 = TK_AFTER; } break; - case 263: /* trigger_time ::= INSTEAD OF */ + case 264: /* trigger_time ::= INSTEAD OF */ { yygotominor.yy46 = TK_INSTEAD;} break; - case 265: /* trigger_event ::= DELETE|INSERT */ - case 266: /* trigger_event ::= UPDATE */ + case 266: /* trigger_event ::= DELETE|INSERT */ + case 267: /* trigger_event ::= UPDATE */ {yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;} break; - case 267: /* trigger_event ::= UPDATE OF inscollist */ + case 268: /* trigger_event ::= UPDATE OF inscollist */ {yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;} break; - case 270: /* when_clause ::= */ - case 287: /* key_opt ::= */ + case 271: /* when_clause ::= */ + case 288: /* key_opt ::= */ { yygotominor.yy172 = 0; } break; - case 271: /* when_clause ::= WHEN expr */ - case 288: /* key_opt ::= KEY expr */ + case 272: /* when_clause ::= WHEN expr */ + case 289: /* key_opt ::= KEY expr */ { yygotominor.yy172 = yymsp[0].minor.yy172; } break; - case 272: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { if( yymsp[-2].minor.yy243 ){ yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243; @@ -73486,25 +75785,25 @@ static void yy_reduce( yygotominor.yy243 = yymsp[-2].minor.yy243; } break; - case 273: /* trigger_cmd_list ::= */ + case 274: /* trigger_cmd_list ::= */ { yygotominor.yy243 = 0; } break; - case 274: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */ + case 275: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */ { yygotominor.yy243 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy410, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); } break; - case 275: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */ + case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */ {yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy410, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);} break; - case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */ + case 277: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */ {yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy410, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);} break; - case 277: /* trigger_cmd ::= DELETE FROM nm where_opt */ + case 278: /* trigger_cmd ::= DELETE FROM nm where_opt */ {yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy410, yymsp[0].minor.yy172);} break; - case 278: /* trigger_cmd ::= select */ + case 279: /* trigger_cmd ::= select */ {yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); } break; - case 279: /* expr ::= RAISE LP IGNORE RP */ + case 280: /* expr ::= RAISE LP IGNORE RP */ { yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); if( yygotominor.yy172 ){ @@ -73513,7 +75812,7 @@ static void yy_reduce( } } break; - case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 281: /* expr ::= RAISE LP raisetype COMMA nm RP */ { yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy410); if( yygotominor.yy172 ) { @@ -73522,72 +75821,72 @@ static void yy_reduce( } } break; - case 281: /* raisetype ::= ROLLBACK */ + case 282: /* raisetype ::= ROLLBACK */ {yygotominor.yy46 = OE_Rollback;} break; - case 283: /* raisetype ::= FAIL */ + case 284: /* raisetype ::= FAIL */ {yygotominor.yy46 = OE_Fail;} break; - case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 285: /* cmd ::= DROP TRIGGER ifexists fullname */ { sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46); } break; - case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 286: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172); } break; - case 286: /* cmd ::= DETACH database_kw_opt expr */ + case 287: /* cmd ::= DETACH database_kw_opt expr */ { sqlite3Detach(pParse, yymsp[0].minor.yy172); } break; - case 291: /* cmd ::= REINDEX */ + case 292: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 292: /* cmd ::= REINDEX nm dbnm */ + case 293: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} break; - case 293: /* cmd ::= ANALYZE */ + case 294: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 294: /* cmd ::= ANALYZE nm dbnm */ + case 295: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} break; - case 295: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 296: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy410); } break; - case 296: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ + case 297: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ { sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy410); } break; - case 297: /* add_column_fullname ::= fullname */ + case 298: /* add_column_fullname ::= fullname */ { sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373); } break; - case 300: /* cmd ::= create_vtab */ + case 301: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 301: /* cmd ::= create_vtab LP vtabarglist RP */ + case 302: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 302: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */ + case 303: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */ { sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, &yymsp[0].minor.yy410); } break; - case 305: /* vtabarg ::= */ + case 306: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 307: /* vtabargtoken ::= ANY */ - case 308: /* vtabargtoken ::= lp anylist RP */ - case 309: /* lp ::= LP */ - case 311: /* anylist ::= anylist ANY */ + case 308: /* vtabargtoken ::= ANY */ + case 309: /* vtabargtoken ::= lp anylist RP */ + case 310: /* lp ::= LP */ + case 312: /* anylist ::= anylist ANY */ {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; }; @@ -73709,7 +76008,8 @@ SQLITE_PRIVATE void sqlite3Parser( if( yypParser->yyidx<0 ){ #if YYSTACKDEPTH<=0 if( yypParser->yystksz <=0 ){ - memset(&yyminorunion, 0, sizeof(yyminorunion)); + /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ + yyminorunion = yyzerominor; yyStackOverflow(yypParser, &yyminorunion); return; } @@ -73847,7 +76147,7 @@ SQLITE_PRIVATE void sqlite3Parser( ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.138 2008/01/22 23:37:10 drh Exp $ +** $Id: tokenize.c,v 1.142 2008/04/28 18:46:43 drh Exp $ */ /* @@ -74065,7 +76365,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = { ** Return the length of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ -static int getToken(const unsigned char *z, int *tokenType){ +SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ int i, c; switch( *z ){ case ' ': case '\t': case '\n': case '\f': case '\r': { @@ -74315,9 +76615,6 @@ static int getToken(const unsigned char *z, int *tokenType){ *tokenType = TK_ILLEGAL; return 1; } -SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ - return getToken(z, tokenType); -} /* ** Run the parser on the given SQL string. The parser structure is @@ -74333,11 +76630,13 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr int tokenType; int lastTokenParsed = -1; sqlite3 *db = pParse->db; + int mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->activeVdbeCnt==0 ){ db->u1.isInterrupted = 0; } pParse->rc = SQLITE_OK; + pParse->zTail = pParse->zSql = zSql; i = 0; pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3_malloc); if( pEngine==0 ){ @@ -74351,14 +76650,13 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr assert( pParse->nVarExpr==0 ); assert( pParse->nVarExprAlloc==0 ); assert( pParse->apVarExpr==0 ); - pParse->zTail = pParse->zSql = zSql; while( !db->mallocFailed && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = (u8*)&zSql[i]; assert( pParse->sLastToken.dyn==0 ); - pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType); + pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); i += pParse->sLastToken.n; - if( SQLITE_MAX_SQL_LENGTH>0 && i>SQLITE_MAX_SQL_LENGTH ){ + if( i>mxSqlLen ){ pParse->rc = SQLITE_TOOBIG; break; } @@ -74430,6 +76728,9 @@ abort_parse: pParse->nTableLock = 0; } #endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_free(pParse->apVtabLock); +#endif if( !IN_DECLARE_VTAB ){ /* If the pParse->declareVtab flag is set, do not delete any table @@ -74738,7 +77039,7 @@ SQLITE_API int sqlite3_complete16(const void *zSql){ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.421 2008/03/07 21:37:19 drh Exp $ +** $Id: main.c,v 1.439 2008/05/13 13:27:34 drh Exp $ */ #ifdef SQLITE_ENABLE_FTS3 /************** Include fts3.h in the middle of main.c ***********************/ @@ -74781,6 +77082,7 @@ SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; } SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } +#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) /* ** If the following function pointer is not NULL and if ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing @@ -74788,6 +77090,7 @@ SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } ** are intended for debugging activity only. */ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; +#endif /* ** If the following global variable points to a string which is the @@ -74798,12 +77101,22 @@ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; */ SQLITE_API char *sqlite3_temp_directory = 0; +/* +** Routine needed to support the testcase() macro. +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int x){ + static int dummy = 0; + dummy += x; +} +#endif + /* ** Return true if the buffer z[0..n-1] contains all spaces. */ static int allSpaces(const char *z, int n){ - while( n>0 && z[--n]==' ' ){} + while( n>0 && z[n-1]==' ' ){ n--; } return n==0; } @@ -74993,7 +77306,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){ int i; int inTrans = 0; assert( sqlite3_mutex_held(db->mutex) ); - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1); + sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC); for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ @@ -75004,7 +77317,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){ } } sqlite3VtabRollback(db); - sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC); if( db->flags&SQLITE_InternChanges ){ sqlite3ExpirePreparedStatements(db); @@ -75045,7 +77358,7 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ case SQLITE_CONSTRAINT: z = "constraint failed"; break; case SQLITE_MISMATCH: z = "datatype mismatch"; break; case SQLITE_MISUSE: z = "library routine called out of sequence";break; - case SQLITE_NOLFS: z = "kernel lacks large file support"; break; + case SQLITE_NOLFS: z = "large file support is disabled"; break; case SQLITE_AUTH: z = "authorization denied"; break; case SQLITE_FORMAT: z = "auxiliary database format error"; break; case SQLITE_RANGE: z = "bind or column index out of range"; break; @@ -75292,7 +77605,6 @@ SQLITE_API int sqlite3_create_function( ){ int rc; sqlite3_mutex_enter(db->mutex); - assert( !db->mallocFailed ); rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); @@ -75681,6 +77993,81 @@ static int createCollation( /* +** This array defines hard upper bounds on limit values. The +** initializer must be kept in sync with the SQLITE_LIMIT_* +** #defines in sqlite3.h. +*/ +static const int aHardLimit[] = { + SQLITE_MAX_LENGTH, + SQLITE_MAX_SQL_LENGTH, + SQLITE_MAX_COLUMN, + SQLITE_MAX_EXPR_DEPTH, + SQLITE_MAX_COMPOUND_SELECT, + SQLITE_MAX_VDBE_OP, + SQLITE_MAX_FUNCTION_ARG, + SQLITE_MAX_ATTACHED, + SQLITE_MAX_LIKE_PATTERN_LENGTH, + SQLITE_MAX_VARIABLE_NUMBER, +}; + +/* +** Make sure the hard limits are set to reasonable values +*/ +#if SQLITE_MAX_LENGTH<100 +# error SQLITE_MAX_LENGTH must be at least 100 +#endif +#if SQLITE_MAX_SQL_LENGTH<100 +# error SQLITE_MAX_SQL_LENGTH must be at least 100 +#endif +#if SQLITE_MAX_SQL_LENGTH>SQLITE_MAX_LENGTH +# error SQLITE_MAX_SQL_LENGTH must not be greater than SQLITE_MAX_LENGTH +#endif +#if SQLITE_MAX_COMPOUND_SELECT<2 +# error SQLITE_MAX_COMPOUND_SELECT must be at least 2 +#endif +#if SQLITE_MAX_VDBE_OP<40 +# error SQLITE_MAX_VDBE_OP must be at least 40 +#endif +#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>255 +# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 255 +#endif +#if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30 +# error SQLITE_MAX_ATTACH must be between 0 and 30 +#endif +#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1 +# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1 +#endif +#if SQLITE_MAX_VARIABLE_NUMBER<1 +# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1 +#endif + + +/* +** Change the value of a limit. Report the old value. +** If an invalid limit index is supplied, report -1. +** Make no changes but still report the old value if the +** new limit is negative. +** +** A new lower limit does not shrink existing constructs. +** It merely prevents new constructs that exceed the limit +** from forming. +*/ +SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ + int oldLimit; + if( limitId<0 || limitId>=SQLITE_N_LIMIT ){ + return -1; + } + oldLimit = db->aLimit[limitId]; + if( newLimit>=0 ){ + if( newLimit>aHardLimit[limitId] ){ + newLimit = aHardLimit[limitId]; + } + db->aLimit[limitId] = newLimit; + } + return oldLimit; +} + +/* ** This routine does the work of opening a database on behalf of ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" ** is UTF-8 encoded. @@ -75721,8 +78108,11 @@ static int openDatabase( db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; + assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); + memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->autoCommit = 1; db->nextAutovac = -1; + db->nextPagesize = 0; db->flags |= SQLITE_ShortColNames #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt @@ -75753,13 +78143,12 @@ static int openDatabase( createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); - if( db->mallocFailed || - (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 - ){ - assert( db->mallocFailed ); + if( db->mallocFailed ){ db->magic = SQLITE_MAGIC_SICK; goto opendb_out; } + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); + assert( db->pDfltColl!=0 ); /* Also add a UTF-8 case-insensitive collation sequence. */ createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); @@ -75907,12 +78296,8 @@ SQLITE_API int sqlite3_open16( rc = openDatabase(zFilename8, ppDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); assert( *ppDb || rc==SQLITE_NOMEM ); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); - if( rc!=SQLITE_OK ){ - sqlite3_close(*ppDb); - *ppDb = 0; - } + if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ + ENC(*ppDb) = SQLITE_UTF16NATIVE; } } sqlite3ValueFree(pVal); @@ -76094,8 +78479,8 @@ SQLITE_API int sqlite3_table_column_metadata( int autoinc = 0; /* Ensure the database schema has been loaded */ - (void)sqlite3SafetyOn(db); sqlite3_mutex_enter(db->mutex); + (void)sqlite3SafetyOn(db); sqlite3BtreeEnterAll(db); rc = sqlite3Init(db, &zErrMsg); sqlite3BtreeLeaveAll(db); @@ -76242,11 +78627,19 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo ** Interface to the testing logic. */ SQLITE_API int sqlite3_test_control(int op, ...){ - va_list ap; int rc = 0; +#ifndef SQLITE_OMIT_BUILTIN_TEST + va_list ap; va_start(ap, op); switch( op ){ -#ifndef SQLITE_OMIT_FAULTINJECTOR + /* + ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat) + ** + ** Configure a fault injector. The specific fault injector is + ** identified by the fault_id argument. (ex: SQLITE_FAULTINJECTOR_MALLOC) + ** The fault will occur after a delay of nDelay calls. The fault + ** will repeat nRepeat times. + */ case SQLITE_TESTCTRL_FAULT_CONFIG: { int id = va_arg(ap, int); int nDelay = va_arg(ap, int); @@ -76254,24 +78647,89 @@ SQLITE_API int sqlite3_test_control(int op, ...){ sqlite3FaultConfig(id, nDelay, nRepeat); break; } + + /* + ** sqlite3_test_control(FAULT_FAILURES, fault_id) + ** + ** Return the number of faults (both hard and benign faults) that have + ** occurred since the injector identified by fault_id) was last configured. + */ case SQLITE_TESTCTRL_FAULT_FAILURES: { int id = va_arg(ap, int); rc = sqlite3FaultFailures(id); break; } + + /* + ** sqlite3_test_control(FAULT_BENIGN_FAILURES, fault_id) + ** + ** Return the number of benign faults that have occurred since the + ** injector identified by fault_id was last configured. + */ case SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES: { int id = va_arg(ap, int); rc = sqlite3FaultBenignFailures(id); break; } + + /* + ** sqlite3_test_control(FAULT_PENDING, fault_id) + ** + ** Return the number of successes that will occur before the next + ** scheduled failure on fault injector fault_id. + ** If no failures are scheduled, return -1. + */ case SQLITE_TESTCTRL_FAULT_PENDING: { int id = va_arg(ap, int); rc = sqlite3FaultPending(id); break; } -#endif /* SQLITE_OMIT_FAULTINJECTOR */ + + /* + ** Save the current state of the PRNG. + */ + case SQLITE_TESTCTRL_PRNG_SAVE: { + sqlite3PrngSaveState(); + break; + } + + /* + ** Restore the state of the PRNG to the last state saved using + ** PRNG_SAVE. If PRNG_SAVE has never before been called, then + ** this verb acts like PRNG_RESET. + */ + case SQLITE_TESTCTRL_PRNG_RESTORE: { + sqlite3PrngRestoreState(); + break; + } + + /* + ** Reset the PRNG back to its uninitialized state. The next call + ** to sqlite3_randomness() will reseed the PRNG using a single call + ** to the xRandomness method of the default VFS. + */ + case SQLITE_TESTCTRL_PRNG_RESET: { + sqlite3PrngResetState(); + break; + } + + /* + ** sqlite3_test_control(BITVEC_TEST, size, program) + ** + ** Run a test against a Bitvec object of size. The program argument + ** is an array of integers that defines the test. Return -1 on a + ** memory allocation error, 0 on success, or non-zero for an error. + ** See the sqlite3BitvecBuiltinTest() for additional information. + */ + case SQLITE_TESTCTRL_BITVEC_TEST: { + int sz = va_arg(ap, int); + int *aProg = va_arg(ap, int*); + rc = sqlite3BitvecBuiltinTest(sz, aProg); + break; + } } va_end(ap); +#endif /* SQLITE_OMIT_BUILTIN_TEST */ return rc; } @@ -79906,8 +82364,8 @@ static void snippetOffsetText(Snippet *p){ ** it in this case */ zBuf[0] = ' '; - sprintf(&zBuf[cnt>0], "%d %d %d %d", pMatch->iCol, - pMatch->iTerm, pMatch->iStart, pMatch->nByte); + sqlite3_snprintf(sizeof(zBuf)-1, &zBuf[cnt>0], "%d %d %d %d", + pMatch->iCol, pMatch->iTerm, pMatch->iStart, pMatch->nByte); append(&sb, zBuf); cnt++; } diff --git a/libs/sqlite3/sqlite3.h b/libs/sqlite3/sqlite3.h index 3d4c513..a492b6d 100644 --- a/libs/sqlite3/sqlite3.h +++ b/libs/sqlite3/sqlite3.h @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.291 2008/03/08 12:37:31 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.312 2008/05/12 12:39:56 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -93,8 +93,8 @@ extern "C" { ** with the value (X*1000000 + Y*1000 + Z) where X, Y, and ** Z are the major version, minor version, and release number. */ -#define SQLITE_VERSION "3.5.7" -#define SQLITE_VERSION_NUMBER 3005007 +#define SQLITE_VERSION "3.5.9" +#define SQLITE_VERSION_NUMBER 3005009 /* ** CAPI3REF: Run-Time Library Version Numbers {F10020} @@ -155,7 +155,7 @@ int sqlite3_threadsafe(void); /* ** CAPI3REF: Database Connection Handle {F12000} -** KEYWORDS: {database connection} +** KEYWORDS: {database connection} {database connections} ** ** Each open SQLite database is represented by pointer to an instance of the ** opaque structure named "sqlite3". It is useful to think of an sqlite3 @@ -1591,17 +1591,42 @@ sqlite3_int64 sqlite3_memory_used(void); sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* +** CAPI3REF: Pseudo-Random Number Generator {F17390} +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random ROWIDs when inserting new records into a table that +** already uses the largest possible ROWID. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** appliations to access the same PRNG for other purposes. +** +** A call to this routine stores N bytes of randomness into buffer P. +** +** The first time this routine is invoked (either internally or by +** the application) the PRNG is seeded using randomness obtained +** from the xRandomness method of the default [sqlite3_vfs] object. +** On all subsequent invocations, the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +** +** INVARIANTS: +** +** {F17392} The [sqlite3_randomness(N,P)] interface writes N bytes of +** high-quality pseudo-randomness into buffer P. +*/ +void sqlite3_randomness(int N, void *P); + +/* ** CAPI3REF: Compile-Time Authorization Callbacks {F12500} ** ** This routine registers a authorizer callback with a particular -** database connection, supplied in the first argument. +** [database connection], supplied in the first argument. ** The authorizer callback is invoked as SQL statements are being compiled ** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], ** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various ** points during the compilation process, as logic is being created ** to perform various actions, the authorizer callback is invoked to ** see if those actions are allowed. The authorizer callback should -** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the ** specific action but allow the SQL statement to continue to be ** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be ** rejected with an error. If the authorizer callback returns @@ -1614,9 +1639,9 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** [sqlite3_prepare_v2()] or equivalent call that triggered the ** authorizer will fail with an error message explaining that ** access is denied. If the authorizer code is [SQLITE_READ] -** and the callback returns [SQLITE_IGNORE] then the prepared -** statement is constructed to insert a NULL value in place of -** the table column that would have +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have ** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] ** return can be used to deny an untrusted user access to individual ** columns of a table. @@ -1629,7 +1654,8 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** parameters to the callback are zero-terminated strings that contain ** additional details about the action to be authorized. ** -** An authorizer is used when preparing SQL statements from an untrusted +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted ** source, to ensure that the SQL statements do not try to access data ** that they are not allowed to see, or that they do not try to ** execute malicious statements that damage the database. For @@ -1637,8 +1663,13 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag); ** SQL queries for evaluation by a database. But the application does ** not want the user to be able to make arbitrary changes to the ** database. An authorizer could then be put in place while the -** user-entered SQL is being prepared that disallows everything -** except SELECT statements. +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. ** ** Only a single authorizer can be in place on a database connection ** at a time. Each call to sqlite3_set_authorizer overrides the @@ -1953,6 +1984,9 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** The third options is behavior that is always used for [sqlite3_open()] ** and [sqlite3_open16()]. ** +** If the 3rd parameter to [sqlite3_open_v2()] is not one of the +** combinations shown above then the behavior is undefined. +** ** If the filename is ":memory:", then an private ** in-memory database is created for the connection. This in-memory ** database will vanish when the database connection is closed. Future @@ -2131,6 +2165,113 @@ const void *sqlite3_errmsg16(sqlite3*); typedef struct sqlite3_stmt sqlite3_stmt; /* +** CAPI3REF: Run-time Limits {F12760} +** +** This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct. The function returns the old limit. +** +** If the new limit is a negative number, the limit is unchanged. +** For the limit category of SQLITE_LIMIT_XYZ there is a hard upper +** bound set by a compile-time C-preprocess macro named SQLITE_MAX_XYZ. +** (The "_LIMIT_" in the name is changed to "_MAX_".) +** Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper limit. +** +** Run time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** webbrowser that has its own databases for storing history and +** separate databases controlled by javascript applications downloaded +** off the internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attach. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** This interface is currently considered experimental and is subject +** to change or removal without prior notice. +** +** INVARIANTS: +** +** {F12762} A successful call to [sqlite3_limit(D,C,V)] where V is +** positive changes the +** limit on the size of construct C in [database connection] D +** to the lessor of V and the hard upper bound on the size +** of C that is set at compile-time. +** +** {F12766} A successful call to [sqlite3_limit(D,C,V)] where V is negative +** leaves the state of [database connection] D unchanged. +** +** {F12769} A successful call to [sqlite3_limit(D,C,V)] returns the +** value of the limit on the size of construct C in +** in [database connection] D as it was prior to the call. +*/ +int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories {F12790} +** KEYWORDS: {limit category} {limit categories} +** +** These constants define various aspects of a [database connection] +** that can be limited in size by calls to [sqlite3_limit()]. +** The meanings of the various limits are as follows: +** +**
    +**
    SQLITE_LIMIT_LENGTH
    +**
    The maximum size of any +** string or blob or table row.
    +** +**
    SQLITE_LIMIT_SQL_LENGTH
    +**
    The maximum length of an SQL statement.
    +** +**
    SQLITE_LIMIT_COLUMN
    +**
    The maximum number of columns in a table definition or in the +** result set of a SELECT or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
    +** +**
    SQLITE_LIMIT_EXPR_DEPTH
    +**
    The maximum depth of the parse tree on any expression.
    +** +**
    SQLITE_LIMIT_COMPOUND_SELECT
    +**
    The maximum number of terms in a compound SELECT statement.
    +** +**
    SQLITE_LIMIT_VDBE_OP
    +**
    The maximum number of instructions in a virtual machine program +** used to implement an SQL statement.
    +** +**
    SQLITE_LIMIT_FUNCTION_ARG
    +**
    The maximum number of arguments on a function.
    +** +**
    SQLITE_LIMIT_ATTACHED
    +**
    The maximum number of attached databases.
    +** +**
    SQLITE_LIMIT_LIKE_PATTERN_LENGTH
    +**
    The maximum length of the pattern argument to the LIKE or +** GLOB operators.
    +** +**
    SQLITE_LIMIT_VARIABLE_NUMBER
    +**
    The maximum number of variables in an SQL statement that can +** be bound.
    +**
    +*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 + +/* ** CAPI3REF: Compiling An SQL Statement {F13010} ** ** To execute an SQL query, it must first be compiled into a byte-code @@ -2149,7 +2290,11 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** If nByte is non-negative, then it is the maximum number of ** bytes read from zSql. When nByte is non-negative, the ** zSql string ends at either the first '\000' or '\u0000' character or -** until the nByte-th byte, whichever comes first. {END} +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be had by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes.{END} ** ** *pzTail is made to point to the first byte past the end of the ** first SQL statement in zSql. These routines only compiles the first @@ -2215,7 +2360,7 @@ typedef struct sqlite3_stmt sqlite3_stmt; ** read from zSql is read up to the first zero terminator. ** ** {F13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)] -** and its variants is non-negative, then nBytes bytes +** and its variants is non-negative, then at most nBytes bytes ** SQL text is read from zSql. ** ** {F13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants @@ -2294,12 +2439,39 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Dynamically Typed Value Object {F15000} +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} ** ** SQLite uses the sqlite3_value object to represent all values -** that are or can be stored in a database table. +** that can be stored in a database table. ** SQLite uses dynamic typing for the values it stores. ** Values stored in sqlite3_value objects can be ** be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. A internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with SQLITE_THREADSAFE=0 and with [sqlite3_threadsafe()] returning 0) +** then there is no distinction between +** protected and unprotected sqlite3_value objects and they can be +** used interchangable. However, for maximum code portability it +** is recommended that applications make the distinction between +** between protected and unprotected sqlite3_value objects even if +** they are single threaded. +** +** The sqlite3_value objects that are passed as parameters into the +** implementation of application-defined SQL functions are protected. +** The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. All other +** interfaces that use sqlite3_value require protected sqlite3_value objects. */ typedef struct Mem sqlite3_value; @@ -2351,8 +2523,7 @@ typedef struct sqlite3_context sqlite3_context; ** In those ** routines that have a fourth argument, its value is the number of bytes ** in the parameter. To be clear: the value is the number of bytes -** in the value, not the number of characters. The number -** of bytes does not include the zero-terminator at the end of strings. +** in the value, not the number of characters. ** If the fourth parameter is negative, the length of the string is ** number of bytes up to the first zero terminator. ** @@ -2461,6 +2632,10 @@ typedef struct sqlite3_context sqlite3_context; ** ** {F13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound ** is a blob of L bytes, or a zero-length blob if L is negative. +** +** {F13551} In calls to [sqlite3_bind_value(S,N,V)] the V argument may +** be either a [protected sqlite3_value] object or an +** [unprotected sqlite3_value] object. */ int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); int sqlite3_bind_double(sqlite3_stmt*, int, double); @@ -2504,11 +2679,12 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*); ** ** This routine returns a pointer to the name of the n-th ** SQL parameter in a [prepared statement]. -** SQL parameters of the form ":AAA" or "@AAA" or "$AAA" have a name -** which is the string ":AAA" or "@AAA" or "$VVV". -** In other words, the initial ":" or "$" or "@" +** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" ** is included as part of the name. -** Parameters of the form "?" or "?NNN" have no name. +** Parameters of the form "?" without a following integer have no name. ** ** The first host parameter has an index of 1, not 0. ** @@ -2528,8 +2704,7 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*); ** a UTF-8 rendering of the name of the SQL parameter in ** [prepared statement] S having index N, or ** NULL if there is no SQL parameter with index N or if the -** parameter with index N is an anonymous parameter "?" or -** a numbered parameter "?NNN". +** parameter with index N is an anonymous parameter "?". */ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); @@ -2826,7 +3001,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int); ** new "v2" interface is recommended for new applications but the legacy ** interface will continue to be supported. ** -** In the lagacy interface, the return value will be either [SQLITE_BUSY], +** In the legacy interface, the return value will be either [SQLITE_BUSY], ** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. ** With the "v2" interface, any of the other [SQLITE_OK | result code] ** or [SQLITE_IOERR_READ | extended result code] might be returned as @@ -3019,6 +3194,15 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); ** but leaves the result in UTF-16 in native byte order instead of UTF-8. ** The zero terminator is not included in this count. ** +** The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like +** [sqlite3_value_int()], [sqlite3_value_text()], or [sqlite3_value_bytes()], +** then the behavior is undefined. +** ** These routines attempt to convert the value where appropriate. For ** example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to do the conversion @@ -3160,7 +3344,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); ** [prepared statement] S. ** ** {F13830} The [sqlite3_column_value(S,N)] interface returns a -** pointer to the [sqlite3_value] object that for the +** pointer to an [unprotected sqlite3_value] object for the ** Nth column in the current row of the result set for ** [prepared statement] S. */ @@ -3350,6 +3534,12 @@ int sqlite3_reset(sqlite3_stmt *pStmt); ** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finializer ** function L will always be invoked exactly once if the ** step function S is called one or more times. +** +** {F16142} When SQLite invokes either the xFunc or xStep function of +** an application-defined SQL function or aggregate created +** by [sqlite3_create_function()] or [sqlite3_create_function16()], +** then the array of [sqlite3_value] objects passed as the +** third parameter are always [protected sqlite3_value] objects. */ int sqlite3_create_function( sqlite3 *db, @@ -3412,14 +3602,18 @@ int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); ** to [sqlite3_create_function()] and [sqlite3_create_function16()] ** define callbacks that implement the SQL functions and aggregates. ** The 4th parameter to these callbacks is an array of pointers to -** [sqlite3_value] objects. There is one [sqlite3_value] object for +** [protected sqlite3_value] objects. There is one [sqlite3_value] object for ** each parameter to the SQL function. These routines are used to ** extract values from the [sqlite3_value] objects. ** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** ** These routines work just like the corresponding ** [sqlite3_column_blob | sqlite3_column_* routines] except that -** these routines take a single [sqlite3_value*] pointer instead -** of an [sqlite3_stmt*] pointer and an integer column number. +** these routines take a single [protected sqlite3_value] object pointer +** instead of an [sqlite3_stmt*] pointer and an integer column number. ** ** The sqlite3_value_text16() interface extracts a UTF16 string ** in the native byte-order of the host machine. The @@ -3441,16 +3635,13 @@ int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); ** or [sqlite3_value_text16()]. ** ** These routines must be called from the same thread as -** the SQL function that supplied the sqlite3_value* parameters. -** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] -** interface, then these routines should be called from the same thread -** that ran [sqlite3_column_value()]. +** the SQL function that supplied the [sqlite3_value*] parameters. ** ** ** INVARIANTS: ** ** {F15103} The [sqlite3_value_blob(V)] interface converts the -** [sqlite3_value] object V into a blob and then returns a +** [protected sqlite3_value] object V into a blob and then returns a ** pointer to the converted value. ** ** {F15106} The [sqlite3_value_bytes(V)] interface returns the @@ -3466,33 +3657,33 @@ int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); ** [sqlite3_value_text16be(V)], or [sqlite3_value_text16le(V)]. ** ** {F15112} The [sqlite3_value_double(V)] interface converts the -** [sqlite3_value] object V into a floating point value and +** [protected sqlite3_value] object V into a floating point value and ** returns a copy of that value. ** ** {F15115} The [sqlite3_value_int(V)] interface converts the -** [sqlite3_value] object V into a 64-bit signed integer and +** [protected sqlite3_value] object V into a 64-bit signed integer and ** returns the lower 32 bits of that integer. ** ** {F15118} The [sqlite3_value_int64(V)] interface converts the -** [sqlite3_value] object V into a 64-bit signed integer and +** [protected sqlite3_value] object V into a 64-bit signed integer and ** returns a copy of that integer. ** ** {F15121} The [sqlite3_value_text(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated UTF-8 +** [protected sqlite3_value] object V into a zero-terminated UTF-8 ** string and returns a pointer to that string. ** ** {F15124} The [sqlite3_value_text16(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated 2-byte +** [protected sqlite3_value] object V into a zero-terminated 2-byte ** aligned UTF-16 native byte order ** string and returns a pointer to that string. ** ** {F15127} The [sqlite3_value_text16be(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated 2-byte +** [protected sqlite3_value] object V into a zero-terminated 2-byte ** aligned UTF-16 big-endian ** string and returns a pointer to that string. ** ** {F15130} The [sqlite3_value_text16le(V)] interface converts the -** [sqlite3_value] object V into a zero-terminated 2-byte +** [protected sqlite3_value] object V into a zero-terminated 2-byte ** aligned UTF-16 little-endian ** string and returns a pointer to that string. ** @@ -3502,12 +3693,12 @@ int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); ** the [sqlite3_value] object V. ** ** {F15136} The [sqlite3_value_numeric_type(V)] interface converts -** the [sqlite3_value] object V into either an integer or +** the [protected sqlite3_value] object V into either an integer or ** a floating point value if it can do so without loss of ** information, and returns one of [SQLITE_NULL], ** [SQLITE_INTEGER], [SQLITE_FLOAT], [SQLITE_TEXT], or ** [SQLITE_BLOB] as appropriate for -** the [sqlite3_value] object V after the conversion attempt. +** the [protected sqlite3_value] object V after the conversion attempt. */ const void *sqlite3_value_blob(sqlite3_value*); int sqlite3_value_bytes(sqlite3_value*); @@ -3592,6 +3783,25 @@ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); void *sqlite3_user_data(sqlite3_context*); /* +** CAPI3REF: Database Connection For Functions {F16250} +** +** The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** INVARIANTS: +** +** {F16253} The [sqlite3_context_db_handle(C)] interface returns a copy of the +** D pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)] +** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that +** registered the SQL function associated with +** [sqlite3_context] C. +*/ +sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* ** CAPI3REF: Function Auxiliary Data {F16270} ** ** The following two functions may be used by scalar SQL functions to @@ -3730,7 +3940,8 @@ typedef void (*sqlite3_destructor_type)(void*); ** modify the text after they return without harm. ** The sqlite3_result_error_code() function changes the error code ** returned by SQLite as a result of an error in a function. By default, -** the error code is SQLITE_ERROR. +** the error code is SQLITE_ERROR. A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. ** ** The sqlite3_result_toobig() interface causes SQLite ** to throw an error indicating that a string or BLOB is to long @@ -3777,11 +3988,14 @@ typedef void (*sqlite3_destructor_type)(void*); ** from [sqlite3_malloc()] before it returns. ** ** The sqlite3_result_value() interface sets the result of -** the application-defined function to be a copy the [sqlite3_value] -** object specified by the 2nd parameter. The +** the application-defined function to be a copy the +** [unprotected sqlite3_value] object specified by the 2nd parameter. The ** sqlite3_result_value() interface makes a copy of the [sqlite3_value] ** so that [sqlite3_value] specified in the parameter may change or ** be deallocated after sqlite3_result_value() returns without harm. +** A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. ** ** If these routines are called from within the different thread ** than the one containing the application-defined function that recieved @@ -3832,26 +4046,27 @@ typedef void (*sqlite3_destructor_type)(void*); ** ** {F16436} The [sqlite3_result_text(C,V,N,D)] interface changes the ** return value of function C to be the UTF8 string -** V up through the first zero or until N bytes are read if N -** is positive. +** V up to the first zero if N is negative +** or the first N bytes of V if N is non-negative. ** ** {F16439} The [sqlite3_result_text16(C,V,N,D)] interface changes the ** return value of function C to be the UTF16 native byte order -** string V up through the first zero or until N bytes are read if N -** is positive. +** string V up to the first zero if N is +** negative or the first N bytes of V if N is non-negative. ** ** {F16442} The [sqlite3_result_text16be(C,V,N,D)] interface changes the ** return value of function C to be the UTF16 big-endian -** string V up through the first zero or until N bytes are read if N -** is positive. +** string V up to the first zero if N is +** is negative or the first N bytes or V if N is non-negative. ** ** {F16445} The [sqlite3_result_text16le(C,V,N,D)] interface changes the ** return value of function C to be the UTF16 little-endian -** string V up through the first zero or until N bytes are read if N -** is positive. +** string V up to the first zero if N is +** negative or the first N bytes of V if N is non-negative. ** ** {F16448} The [sqlite3_result_value(C,V)] interface changes the -** return value of function C to be [sqlite3_value] object V. +** return value of function C to be [unprotected sqlite3_value] +** object V. ** ** {F16451} The [sqlite3_result_zeroblob(C,N)] interface changes the ** return value of function C to be an N-byte blob of all zeros. @@ -4911,7 +5126,7 @@ typedef struct sqlite3_blob sqlite3_blob; ** CAPI3REF: Open A BLOB For Incremental I/O {F17810} ** ** This interfaces opens a handle to the blob located -** in row iRow,, column zColumn, table zTable in database zDb; +** in row iRow, column zColumn, table zTable in database zDb; ** in other words, the same blob that would be selected by: ** **
    @@ -4922,6 +5137,12 @@ typedef struct sqlite3_blob sqlite3_blob;
     ** read and write access. If it is zero, the blob is opened for read 
     ** access.
     **
    +** Note that the database name is not the filename that contains
    +** the database but rather the symbolic name of the database that
    +** is assigned when the database is connected using [ATTACH].
    +** For the main database file, the database name is "main".  For
    +** TEMP tables, the database name is "temp".
    +**
     ** On success, [SQLITE_OK] is returned and the new 
     ** [sqlite3_blob | blob handle] is written to *ppBlob. 
     ** Otherwise an error code is returned and 
    @@ -5050,10 +5271,11 @@ int sqlite3_blob_bytes(sqlite3_blob *);
     **          the [sqlite3_blob_read(P,Z,N,X)] interface returns an
     **          appropriate [error code] or [extended error code].
     **
    -** {F17868} If an error occurs during evaluation of [sqlite3_blob_read(D,...)]
    +** {F17868} If an error occurs during evaluation of [sqlite3_blob_read(P,...)]
     **          then subsequent calls to [sqlite3_errcode(D)],
     **          [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] will return
    -**          information approprate for that error.
    +**          information approprate for that error, where D is the
    +**          database handle that was used to open blob handle P.
     */
     int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
     
    @@ -5221,6 +5443,7 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
     ** 
  • SQLITE_MUTEX_STATIC_MEM2 **
  • SQLITE_MUTEX_STATIC_PRNG **
  • SQLITE_MUTEX_STATIC_LRU +**
  • SQLITE_MUTEX_STATIC_LRU2 ** {END} ** ** {F17015} The first two constants cause sqlite3_mutex_alloc() to create @@ -5333,6 +5556,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*); #define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ #define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */ /* ** CAPI3REF: Low-Level Control Of Database Files {F11300} @@ -5394,9 +5618,10 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_FAULT_FAILURES 2 #define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES 3 #define SQLITE_TESTCTRL_FAULT_PENDING 4 - - - +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 /* diff --git a/libs/sqlite3/sqlite3ext.h b/libs/sqlite3/sqlite3ext.h index 20c32b6..6c538ff 100644 --- a/libs/sqlite3/sqlite3ext.h +++ b/libs/sqlite3/sqlite3ext.h @@ -15,7 +15,7 @@ ** as extensions by SQLite should #include this file instead of ** sqlite3.h. ** -** @(#) $Id: sqlite3ext.h,v 1.18 2008/03/02 03:32:05 mlcreech Exp $ +** @(#) $Id: sqlite3ext.h,v 1.21 2008/03/19 21:45:51 drh Exp $ */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ @@ -182,6 +182,12 @@ struct sqlite3_api_routines { sqlite3_vfs *(*vfs_find)(const char*); int (*vfs_register)(sqlite3_vfs*,int); int (*vfs_unregister)(sqlite3_vfs*); + int (*xthreadsafe)(void); + void (*result_zeroblob)(sqlite3_context*,int); + void (*result_error_code)(sqlite3_context*,int); + int (*test_control)(int, ...); + void (*randomness)(int,void*); + sqlite3 *(*context_db_handle)(sqlite3_context*); }; /* @@ -342,6 +348,12 @@ struct sqlite3_api_routines { #define sqlite3_vfs_find sqlite3_api->vfs_find #define sqlite3_vfs_register sqlite3_api->vfs_register #define sqlite3_vfs_unregister sqlite3_api->vfs_unregister +#define sqlite3_threadsafe sqlite3_api->xthreadsafe +#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob +#define sqlite3_result_error_code sqlite3_api->result_error_code +#define sqlite3_test_control sqlite3_api->test_control +#define sqlite3_randomness sqlite3_api->randomness +#define sqlite3_context_db_handle sqlite3_api->context_db_handle #endif /* SQLITE_CORE */ #define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; diff --git a/readme.txt b/readme.txt index 1f5107f..021bc83 100644 --- a/readme.txt +++ b/readme.txt @@ -75,9 +75,10 @@ called site-template.htm is used to insert the site. You can customize the template by placing an HTML file called identityname-template.htm in the same directory as the fms binary. In the template, the string [LINKS] will be replaced by a
      list of links and [CONTENT] will be replaced by the page -content. The Freesite will be inserted once a day and contain your last 10 -posts and your trust list if you are publishing it. The site will be inserted -to a USK accessible via: USK@yourpublickey.../fms/0/ +content. [IDENTITYNAME] will be replaced by the name of the identity inserting +the Freesite. The Freesite will be inserted once a day and contain your last +10 posts and your trust list if you are publishing it. The site will be +inserted to a USK accessible via: USK@yourpublickey.../fms/0/ You may add extra files to your Freesite by creating a file called identityname- files.txt that contains a list of files to add to the Freesite. There should diff --git a/src/freenet/introductionpuzzleinserter.cpp b/src/freenet/introductionpuzzleinserter.cpp index 9bb4da8..a381084 100644 --- a/src/freenet/introductionpuzzleinserter.cpp +++ b/src/freenet/introductionpuzzleinserter.cpp @@ -10,53 +10,47 @@ #include #endif -IntroductionPuzzleInserter::IntroductionPuzzleInserter() +IntroductionPuzzleInserter::IntroductionPuzzleInserter():IIndexInserter() { Initialize(); } -IntroductionPuzzleInserter::IntroductionPuzzleInserter(FCPv2 *fcp):IFCPConnected(fcp) +IntroductionPuzzleInserter::IntroductionPuzzleInserter(FCPv2 *fcp):IIndexInserter(fcp) { Initialize(); } void IntroductionPuzzleInserter::CheckForNeededInsert() { - // select all local ids that aren't single use and that aren't currently inserting a puzzle and are publishing a trust list - SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PublishTrustList='true' AND SingleUse='false' AND InsertingPuzzle='false' AND PrivateKey IS NOT NULL AND PrivateKey <> '' ORDER BY LastInsertedPuzzle;"); - - while(!rs.AtEnd()) + // only do 1 insert at a time + if(m_inserting.size()==0) { - std::string localidentityidstr; - DateTime now; - now.SetToGMTime(); - - if(rs.GetField(0)) + // select all local ids that aren't single use and that aren't currently inserting a puzzle and are publishing a trust list + SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID FROM tblLocalIdentity WHERE PublishTrustList='true' AND SingleUse='false' AND PrivateKey IS NOT NULL AND PrivateKey <> '' ORDER BY LastInsertedPuzzle;"); + + while(!rs.AtEnd()) { - localidentityidstr=rs.GetField(0); - } + std::string localidentityidstr; + DateTime now; + now.SetToGMTime(); - // if this identity has any non-solved puzzles for today, we don't need to insert a new puzzle - SQLite3DB::Recordset rs2=m_db->Query("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE Day='"+now.Format("%Y-%m-%d")+"' AND FoundSolution='false' AND LocalIdentityID="+localidentityidstr+";"); + if(rs.GetField(0)) + { + localidentityidstr=rs.GetField(0); + } - // identity doesn't have any non-solved puzzles for today - start a new insert - if(rs2.Empty()==true) - { - StartInsert(rs.GetInt(0)); - } + // if this identity has any non-solved puzzles for today, we don't need to insert a new puzzle + SQLite3DB::Recordset rs2=m_db->Query("SELECT UUID FROM tblIntroductionPuzzleInserts WHERE Day='"+now.Format("%Y-%m-%d")+"' AND FoundSolution='false' AND LocalIdentityID="+localidentityidstr+";"); - rs.Next(); - } -} + // identity doesn't have any non-solved puzzles for today - start a new insert + if(rs2.Empty()==true) + { + StartInsert(rs.GetInt(0)); + } -void IntroductionPuzzleInserter::FCPConnected() -{ - m_db->Execute("UPDATE tblLocalIdentity SET InsertingPuzzle='false';"); -} - -void IntroductionPuzzleInserter::FCPDisconnected() -{ - + rs.Next(); + } + } } void IntroductionPuzzleInserter::GenerateCaptcha(std::string &encodeddata, std::string &solution) @@ -77,33 +71,6 @@ void IntroductionPuzzleInserter::GenerateCaptcha(std::string &encodeddata, std:: } -const bool IntroductionPuzzleInserter::HandleMessage(FCPMessage &message) -{ - - if(message["Identifier"].find("IntroductionPuzzleInserter")==0) - { - - // ignore URIGenerated message - if(message.GetName()=="URIGenerated") - { - return true; - } - - if(message.GetName()=="PutSuccessful") - { - return HandlePutSuccessful(message); - } - - if(message.GetName()=="PutFailed") - { - return HandlePutFailed(message); - } - - } - - return false; -} - const bool IntroductionPuzzleInserter::HandlePutFailed(FCPMessage &message) { SQLite3DB::Statement st; @@ -113,18 +80,19 @@ const bool IntroductionPuzzleInserter::HandlePutFailed(FCPMessage &message) StringFunctions::Split(message["Identifier"],"|",idparts); StringFunctions::Convert(idparts[1],localidentityid); - st=m_db->Prepare("UPDATE tblLocalIdentity SET InsertingPuzzle='false' WHERE LocalIdentityID=?;"); - st.Bind(0,localidentityid); - st.Step(); - st.Finalize(); - - // if fatal error or collision - mark index - if(message["Fatal"]=="true" || message["Code"]=="9") + // non USK + if(idparts[0]==m_fcpuniquename) { - m_db->Execute("UPDATE tblIntroductionPuzzleInserts SET Day='"+idparts[5]+"', InsertIndex="+idparts[2]+", FoundSolution='true' WHERE UUID='"+idparts[3]+"';"); - } + // if fatal error or collision - mark index + if(message["Fatal"]=="true" || message["Code"]=="9") + { + m_db->Execute("UPDATE tblIntroductionPuzzleInserts SET Day='"+idparts[5]+"', InsertIndex="+idparts[2]+", FoundSolution='true' WHERE UUID='"+idparts[3]+"';"); + } - m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutFailed failed to insert puzzle "+idparts[3]); + RemoveFromInsertList(localidentityid); + + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutFailed failed to insert puzzle "+idparts[3]); + } return true; } @@ -139,55 +107,40 @@ const bool IntroductionPuzzleInserter::HandlePutSuccessful(FCPMessage &message) now.SetToGMTime(); StringFunctions::Split(message["Identifier"],"|",idparts); - StringFunctions::Convert(idparts[1],localidentityid); - StringFunctions::Convert(idparts[2],insertindex); - - st=m_db->Prepare("UPDATE tblIntroductionPuzzleInserts SET Day=?, InsertIndex=? WHERE UUID=?;"); - st.Bind(0,idparts[5]); - st.Bind(1,insertindex); - st.Bind(2,idparts[3]); - st.Step(); - st.Finalize(); - st=m_db->Prepare("UPDATE tblLocalIdentity SET InsertingPuzzle='false', LastInsertedPuzzle=? WHERE LocalIdentityID=?;"); - st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S")); - st.Bind(1,localidentityid); - st.Step(); - st.Finalize(); - - m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutSuccessful inserted puzzle "+idparts[3]); - - return true; -} - -void IntroductionPuzzleInserter::Initialize() -{ - m_lastchecked.SetToGMTime(); -} + // non USK + if(idparts[0]==m_fcpuniquename) + { + StringFunctions::Convert(idparts[1],localidentityid); + StringFunctions::Convert(idparts[2],insertindex); -void IntroductionPuzzleInserter::Process() -{ + st=m_db->Prepare("UPDATE tblIntroductionPuzzleInserts SET Day=?, InsertIndex=? WHERE UUID=?;"); + st.Bind(0,idparts[5]); + st.Bind(1,insertindex); + st.Bind(2,idparts[3]); + st.Step(); + st.Finalize(); - DateTime now; + st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedPuzzle=? WHERE LocalIdentityID=?;"); + st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S")); + st.Bind(1,localidentityid); + st.Step(); + st.Finalize(); - now.SetToGMTime(); + RemoveFromInsertList(localidentityid); - if(m_lastchecked<(now-(1.0/1440.0))) - { - CheckForNeededInsert(); - m_lastchecked=now; + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::HandlePutSuccessful inserted puzzle "+idparts[3]); } + return true; } -void IntroductionPuzzleInserter::RegisterWithThread(FreenetMasterThread *thread) +void IntroductionPuzzleInserter::Initialize() { - thread->RegisterFCPConnected(this); - thread->RegisterFCPMessageHandler(this); - thread->RegisterPeriodicProcessor(this); + m_fcpuniquename="IntroductionPuzzleInserter"; } -void IntroductionPuzzleInserter::StartInsert(const long localidentityid) +const bool IntroductionPuzzleInserter::StartInsert(const long &localidentityid) { DateTime now; std::string idstring; @@ -248,15 +201,30 @@ void IntroductionPuzzleInserter::StartInsert(const long localidentityid) message.SetName("ClientPut"); message["URI"]=privatekey+messagebase+"|"+now.Format("%Y-%m-%d")+"|IntroductionPuzzle|"+indexstr+".xml"; - message["Identifier"]="IntroductionPuzzleInserter|"+idstring+"|"+indexstr+"|"+xml.GetUUID()+"|"+message["URI"]; + message["Identifier"]=m_fcpuniquename+"|"+idstring+"|"+indexstr+"|"+xml.GetUUID()+"|"+message["URI"]; message["UploadFrom"]="direct"; message["DataLength"]=xmldatasizestr; m_fcp->SendMessage(message); m_fcp->SendRaw(xmldata.c_str(),xmldata.size()); - m_db->Execute("UPDATE tblLocalIdentity SET InsertingPuzzle='true' WHERE LocalIdentityID="+idstring+";"); + // insert to USK + message.Reset(); + message.SetName("ClientPutComplexDir"); + message["URI"]="USK"+privatekey.substr(3)+messagebase+"|"+now.Format("%Y.%m.%d")+"|IntroductionPuzzle/0/"; + message["Identifier"]=m_fcpuniquename+"USK|"+message["URI"]; + message["DefaultName"]="IntroductionPuzzle.xml"; + message["Files.0.Name"]="IntroductionPuzzle.xml"; + message["Files.0.UplaodFrom"]="direct"; + message["Files.0.DataLength"]=xmldatasizestr; + m_fcp->SendMessage(message); + m_fcp->SendRaw(xmldata.c_str(),xmldata.size()); + m_db->Execute("INSERT INTO tblIntroductionPuzzleInserts(UUID,Type,MimeType,LocalIdentityID,PuzzleData,PuzzleSolution) VALUES('"+xml.GetUUID()+"','captcha','image/bmp',"+idstring+",'"+encodedpuzzle+"','"+solutionstring+"');"); + m_inserting.push_back(localidentityid); + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"IntroductionPuzzleInserter::StartInsert started insert for id "+idstring); + return true; + } diff --git a/src/freenet/messageinserter.cpp b/src/freenet/messageinserter.cpp index 3dc1203..e1a5211 100644 --- a/src/freenet/messageinserter.cpp +++ b/src/freenet/messageinserter.cpp @@ -13,11 +13,14 @@ MessageInserter::MessageInserter(FCPv2 *fcp):IIndexInserter(fcp) void MessageInserter::CheckForNeededInsert() { + DateTime now; + now.SetToGMTime(); bool didinsert=false; // only do 1 insert at a time if(m_inserting.size()==0) { - SQLite3DB::Statement st=m_db->Prepare("SELECT MessageUUID FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.PrivateKey IS NOT NULL AND tblLocalIdentity.PrivateKey <> '' AND tblMessageInserts.Inserted='false';"); + SQLite3DB::Statement st=m_db->Prepare("SELECT MessageUUID FROM tblMessageInserts INNER JOIN tblLocalIdentity ON tblMessageInserts.LocalIdentityID=tblLocalIdentity.LocalIdentityID WHERE tblLocalIdentity.PrivateKey IS NOT NULL AND tblLocalIdentity.PrivateKey <> '' AND tblMessageInserts.Inserted='false' AND tblMessageInserts.SendDate<=?;"); + st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S")); st.Step(); while(st.RowReturned() && m_inserting.size()==0) diff --git a/src/freenet/messagelistinserter.cpp b/src/freenet/messagelistinserter.cpp index f598b51..833b556 100644 --- a/src/freenet/messagelistinserter.cpp +++ b/src/freenet/messagelistinserter.cpp @@ -29,6 +29,12 @@ void MessageListInserter::CheckForNeededInsert() now.SetToGMTime(); previous.SetToGMTime(); + // reset the last inserted xml doc to nothing if the day has changed + if(m_lastchecked.GetDay()!=now.GetDay()) + { + m_lastinsertedxml.clear(); + } + previous.Add(0,0,0,-m_daysbackward); // query for identities that have messages in the past X days and (we haven't inserted lists for in the past 30 minutes OR identity has a record in tmpMessageListInsert) @@ -60,19 +66,27 @@ const bool MessageListInserter::HandlePutFailed(FCPMessage &message) long index; StringFunctions::Split(message["Identifier"],"|",idparts); - StringFunctions::Convert(idparts[1],localidentityid); - StringFunctions::Convert(idparts[2],index); - if(message["Fatal"]=="true" || message["Code"]=="9") + // non USK + if(idparts[0]==m_fcpuniquename) { - SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'false');"); - st.Bind(0,localidentityid); - st.Bind(1,idparts[4]); - st.Bind(2,index); - st.Step(); - } + StringFunctions::Convert(idparts[1],localidentityid); + StringFunctions::Convert(idparts[2],index); - RemoveFromInsertList(localidentityid); + if(message["Fatal"]=="true" || message["Code"]=="9") + { + SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'false');"); + st.Bind(0,localidentityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); + } + + RemoveFromInsertList(localidentityid); + + // reset the last inserted xml doc to nothing so we will try to insert this one again + m_lastinsertedxml[localidentityid]=""; + } return true; @@ -86,29 +100,34 @@ const bool MessageListInserter::HandlePutSuccessful(FCPMessage &message) long index; StringFunctions::Split(message["Identifier"],"|",idparts); - StringFunctions::Convert(idparts[1],localidentityid); - StringFunctions::Convert(idparts[2],index); - SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'true');"); - st.Bind(0,localidentityid); - st.Bind(1,idparts[4]); - st.Bind(2,index); - st.Step(); + // non USK + if(idparts[0]==m_fcpuniquename) + { + StringFunctions::Convert(idparts[1],localidentityid); + StringFunctions::Convert(idparts[2],index); - now.SetToGMTime(); - st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedMessageList=? WHERE LocalIdentityID=?;"); - st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S")); - st.Bind(1,localidentityid); - st.Step(); + SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageListInserts(LocalIdentityID,Day,InsertIndex,Inserted) VALUES(?,?,?,'true');"); + st.Bind(0,localidentityid); + st.Bind(1,idparts[4]); + st.Bind(2,index); + st.Step(); - // delete any record from tmpMessageListInsert - st=m_db->Prepare("DELETE FROM tmpMessageListInsert WHERE LocalIdentityID=?;"); - st.Bind(0,localidentityid); - st.Step(); + now.SetToGMTime(); + st=m_db->Prepare("UPDATE tblLocalIdentity SET LastInsertedMessageList=? WHERE LocalIdentityID=?;"); + st.Bind(0,now.Format("%Y-%m-%d %H:%M:%S")); + st.Bind(1,localidentityid); + st.Step(); + + // delete any record from tmpMessageListInsert + st=m_db->Prepare("DELETE FROM tmpMessageListInsert WHERE LocalIdentityID=?;"); + st.Bind(0,localidentityid); + st.Step(); - RemoveFromInsertList(localidentityid); + RemoveFromInsertList(localidentityid); - m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageListInserter::HandlePutSuccessful successfully inserted MessageList."); + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"MessageListInserter::HandlePutSuccessful successfully inserted MessageList."); + } return true; } @@ -230,23 +249,14 @@ const bool MessageListInserter::StartInsert(const long &localidentityid) m_fcp->SendMessage(message); m_fcp->SendRaw(xmlstr.c_str(),xmlstr.size()); - /* - // insert a USK redirect to the file we just inserted - targeturi=message["URI"]; message.Reset(); - message.SetName("ClientPut"); - message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|MessageList/0/MessageList.xml"; - message["Identifier"]=message["URI"]; - message["UploadFrom"]="redirect"; - message["TargetURI"]=targeturi; - m_fcp->SendMessage(message); - */ - message.Reset(); - message.SetName("ClientPut"); - message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|MessageList/0/MessageList.xml"; - message["Identifier"]=message["URI"]; - message["UploadFrom"]="direct"; - message["DataLength"]=xmlsizestr; + message.SetName("ClientPutComplexDir"); + message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|MessageList/0/"; + message["Identifier"]=m_fcpuniquename+"USK|"+message["URI"]; + message["DefaultName"]="MessageList.xml"; + message["Files.0.Name"]="MessageList.xml"; + message["Files.0.UploadFrom"]="direct"; + message["Files.0.DataLength"]=xmlsizestr; m_fcp->SendMessage(message); m_fcp->SendRaw(xmlstr.c_str(),xmlstr.size()); diff --git a/src/freenet/trustlistinserter.cpp b/src/freenet/trustlistinserter.cpp index 8962d5e..d316790 100644 --- a/src/freenet/trustlistinserter.cpp +++ b/src/freenet/trustlistinserter.cpp @@ -72,23 +72,30 @@ const bool TrustListInserter::HandleMessage(FCPMessage &message) if(message.GetName()=="PutSuccessful") { - m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false', LastInsertedTrustList='"+now.Format("%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";"); - m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");"); - m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListInserter::HandleMessage inserted TrustList xml"); + // non USK + if(idparts[0]=="TrustListInserter") + { + m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false', LastInsertedTrustList='"+now.Format("%Y-%m-%d %H:%M:%S")+"' WHERE LocalIdentityID="+idparts[1]+";"); + m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");"); + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListInserter::HandleMessage inserted TrustList xml"); + } return true; } - if(message.GetName()=="PutFailed") + if(message.GetName()=="PutFailed" && idparts[0]=="TrustListInserter") { - m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false' WHERE LocalIdentityID="+idparts[1]+";"); - m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListInserter::HandleMessage failure inserting TrustList xml. Code="+message["Code"]+" Description="+message["CodeDescription"]); - - // if code 9 (collision), then insert index into inserted table - if(message["Code"]=="9") + // non USK + if(idparts[0]=="TrustListInserter") { - m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");"); - } + m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='false' WHERE LocalIdentityID="+idparts[1]+";"); + m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"TrustListInserter::HandleMessage failure inserting TrustList xml. Code="+message["Code"]+" Description="+message["CodeDescription"]); + // if code 9 (collision), then insert index into inserted table + if(message["Code"]=="9") + { + m_db->Execute("INSERT INTO tblTrustListInserts(LocalIdentityID,Day,InsertIndex) VALUES("+idparts[1]+",'"+idparts[4]+"',"+idparts[2]+");"); + } + } return true; } @@ -205,6 +212,18 @@ void TrustListInserter::StartInsert(const long localidentityid, const std::strin m_fcp->SendMessage(message); m_fcp->SendRaw(data.c_str(),data.size()); + // insert to USK + message.Reset(); + message.SetName("ClientPutComplexDir"); + message["URI"]="USK"+privatekey.substr(3)+m_messagebase+"|"+now.Format("%Y.%m.%d")+"|TrustList/0/"; + message["Identifier"]="TrustListInserterUSK|"+message["URI"]; + message["DefaultName"]="TrustList.xml"; + message["Files.0.Name"]="TrustList.xml"; + message["Files.0.UplaodFrom"]="direct"; + message["Files.0.DataLength"]=datasizestr; + m_fcp->SendMessage(message); + m_fcp->SendRaw(data.c_str(),data.size()); + m_db->Execute("UPDATE tblLocalIdentity SET InsertingTrustList='true' WHERE LocalIdentityID="+localidentityidstr+";"); } diff --git a/src/global.cpp b/src/global.cpp index b81ed6f..9bc8f04 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -120,13 +120,19 @@ void SetupDB() major=1; minor=10; } + if(major==1 && minor==10) + { + ConvertDB0110To0111(); + major=1; + minor=11; + } } else { - db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,10);"); + db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,11);"); } - db->Execute("UPDATE tblDBVersion SET Major=1, Minor=10;"); + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=11;"); db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\ Option TEXT UNIQUE,\ @@ -150,12 +156,12 @@ void SetupDB() LastInsertedPuzzle DATETIME,\ InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\ LastInsertedTrustList DATETIME,\ - InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\ LastInsertedBoardList DATETIME,\ - InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\ LastInsertedMessageList DATETIME,\ LastInsertedFreesite DATETIME,\ - DateCreated DATETIME\ + DateCreated DATETIME,\ + MinMessageDelay INTEGER DEFAULT 0,\ + MaxMessageDelay INTEGER DEFAULT 0\ );"); db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\ @@ -204,8 +210,6 @@ void SetupDB() LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ AddedMethod TEXT,\ - MessageTrustComment TEXT,\ - TrustListTrustComment TEXT,\ Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\ );"); @@ -344,7 +348,8 @@ void SetupDB() InsertIndex INTEGER,\ MessageUUID TEXT UNIQUE,\ MessageXML TEXT,\ - Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\ + Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false',\ + SendDate DATETIME\ );"); db->Execute("CREATE TABLE IF NOT EXISTS tblFileInserts(\ @@ -662,6 +667,73 @@ void ConvertDB0109To0110() db->Execute("UPDATE tblDBVersion SET Major=1, Minor=10;"); } +void ConvertDB0110To0111() +{ + /* + Drop MessageTrustComment, TrustListTrustComment FROM tblIdentity + + Drop InsertingMessageList, InsertingBoardList FROM tblLocalIdentity + Add MinMessageDelay, MaxMessageDelay to tblLocalIdentity Default 0 + + Add SendDate to tblMessageInserts + */ + SQLite3DB::DB *db=SQLite3DB::DB::Instance(); + + db->Execute("ALTER TABLE tblMessageInserts ADD COLUMN SendDate DATETIME;"); + + db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;"); + db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;"); + db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\ + LocalIdentityID INTEGER PRIMARY KEY,\ + Name TEXT,\ + PublicKey TEXT UNIQUE,\ + PrivateKey TEXT UNIQUE,\ + SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ + PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ + PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ + PublishFreesite BOOL CHECK(PublishFreesite IN('true','false')) DEFAULT 'false',\ + FreesiteEdition INTEGER,\ + InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\ + LastInsertedIdentity DATETIME,\ + InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\ + LastInsertedPuzzle DATETIME,\ + InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\ + LastInsertedTrustList DATETIME,\ + LastInsertedBoardList DATETIME,\ + LastInsertedMessageList DATETIME,\ + LastInsertedFreesite DATETIME,\ + DateCreated DATETIME,\ + MinMessageDelay INTEGER DEFAULT 0,\ + MaxMessageDelay INTEGER DEFAULT 0\ + );"); + db->Execute("INSERT INTO tblLocalIdentity SELECT LocalIdentityID,Name,PublicKey,PrivateKey,SingleUse,PublishTrustList,PublishBoardList,PublishFreesite,FreesiteEdition,InsertingIdentity,LastInsertedIdentity,InsertingPuzzle,LastInsertedPuzzle,InsertingTrustList,LastInsertedTrustList,LastInsertedBoardList,LastInsertedMessageList,LastInsertedFreesite,DateCreated,0,0 FROM tblLocalIdentityTemp;"); + db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;"); + + db->Execute("CREATE TEMPORARY TABLE tblIdentityTemp AS SELECT * FROM tblIdentity;"); + db->Execute("DROP TABLE IF EXISTS tblIdentity;"); + db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\ + IdentityID INTEGER PRIMARY KEY,\ + PublicKey TEXT UNIQUE,\ + Name TEXT,\ + SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\ + PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\ + PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\ + FreesiteEdition INTEGER,\ + DateAdded DATETIME,\ + LastSeen DATETIME,\ + LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT NULL,\ + AddedMethod TEXT,\ + Hidden BOOL CHECK(Hidden IN('true','false')) DEFAULT 'false'\ + );"); + db->Execute("INSERT INTO tblIdentity SELECT IdentityID,PublicKey,Name,SingleUse,PublishTrustList,PublishBoardList,FreesiteEdition,DateAdded,LastSeen,LocalMessageTrust,PeerMessageTrust,LocalTrustListTrust,PeerTrustListTrust,AddedMethod,Hidden FROM tblIdentityTemp;"); + db->Execute("DROP TABLE IF EXISTS tblIdentityTemp;"); + + db->Execute("UPDATE tblDBVersion SET Major=1, Minor=11;"); +} + void SetupDefaultOptions() { // OptionValue should always be inserted as a string, even if the option really isn't a string - just to keep the field data type consistent diff --git a/src/http/pages/localidentitiespage.cpp b/src/http/pages/localidentitiespage.cpp index c06ee5b..f3a4967 100644 --- a/src/http/pages/localidentitiespage.cpp +++ b/src/http/pages/localidentitiespage.cpp @@ -21,26 +21,36 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c std::vector publishtrustlist; std::vector publishboardlist; std::vector publishfreesite; + std::vector mindelay; + std::vector maxdelay; CreateArgArray(queryvars,"chkidentityid",ids); CreateArgArray(queryvars,"singleuse",singleuse); CreateArgArray(queryvars,"publishtrustlist",publishtrustlist); CreateArgArray(queryvars,"publishboardlist",publishboardlist); CreateArgArray(queryvars,"publishfreesite",publishfreesite); + CreateArgArray(queryvars,"mindelay",mindelay); + CreateArgArray(queryvars,"maxdelay",maxdelay); if((*queryvars.find("formaction")).second=="update") { - SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=?, PublishBoardList=?, PublishFreesite=? WHERE LocalIdentityID=?;"); + SQLite3DB::Statement update=m_db->Prepare("UPDATE tblLocalIdentity SET SingleUse=?, PublishTrustList=?, PublishBoardList=?, PublishFreesite=?, MinMessageDelay=?, MaxMessageDelay=? WHERE LocalIdentityID=?;"); for(int i=0; i"; // content+=""; - content+="
  • "; + content+="
    NameSingle UsePublish Trust ListPublish Board ListPublish FreesiteAnnounced? *
    "; - SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID,tblLocalIdentity.Name,tblLocalIdentity.PublicKey,tbLLocalIdentity.PublishTrustList,tblLocalIdentity.SingleUse,tblLocalIdentity.PublishBoardList,tblIdentity.IdentityID,tblLocalIdentity.PublishFreesite FROM tblLocalIdentity LEFT JOIN tblIdentity ON tblLocalIdentity.PublicKey=tblIdentity.PublicKey ORDER BY tblLocalIdentity.Name;"); + SQLite3DB::Statement st=m_db->Prepare("SELECT LocalIdentityID,tblLocalIdentity.Name,tblLocalIdentity.PublicKey,tbLLocalIdentity.PublishTrustList,tblLocalIdentity.SingleUse,tblLocalIdentity.PublishBoardList,tblIdentity.IdentityID,tblLocalIdentity.PublishFreesite,tblLocalIdentity.MinMessageDelay,tblLocalIdentity.MaxMessageDelay FROM tblLocalIdentity LEFT JOIN tblIdentity ON tblLocalIdentity.PublicKey=tblIdentity.PublicKey ORDER BY tblLocalIdentity.Name;"); st.Step(); SQLite3DB::Statement trustst=m_db->Prepare("SELECT COUNT(*) FROM tblPeerTrust LEFT JOIN tblIdentity ON tblPeerTrust.TargetIdentityID=tblIdentity.IdentityID WHERE tblIdentity.PublicKey=? GROUP BY tblPeerTrust.TargetIdentityID;"); @@ -202,6 +212,8 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c std::string singleuse=""; std::string publishboardlist=""; std::string publishfreesite=""; + std::string minmessagedelay="0"; + std::string maxmessagedelay="0"; st.ResultText(0,id); st.ResultText(1,name); @@ -210,6 +222,8 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c st.ResultText(4,singleuse); st.ResultText(5,publishboardlist); st.ResultText(7,publishfreesite); + st.ResultText(8,minmessagedelay); + st.ResultText(9,maxmessagedelay); content+=""; // content+=""; @@ -218,6 +232,8 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c content+=""; content+=""; content+=""; + content+=""; + content+=""; trustst.Bind(0,publickey); trustst.Step(); @@ -256,6 +272,7 @@ const std::string LocalIdentitiesPage::GeneratePage(const std::string &method, c content+="
    NameSingle UsePublish Trust ListPublish Board ListPublish FreesiteMin Message DelayMax Message DelayAnnounced? *
    "+CreateTrueFalseDropDown("publishtrustlist["+countstr+"]",publishtrustlist)+""+CreateTrueFalseDropDown("publishboardlist["+countstr+"]",publishboardlist)+""+CreateTrueFalseDropDown("publishfreesite["+countstr+"]",publishfreesite)+"
    "; content+="

    * An identity is considered successfully announced when you have downloaded a trust list from someone that contains the identity. The number in parenthesis is how many trust lists that identity appears in.

    "; content+="

    Single Use Identities will automatically be deleted 7 days after creation.

    "; + content+="

    Messages that each identity sends may be delayed by a random number of minutes between min and max. Set both to 0 to send messages as soon as possible.

    "; return "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"+StringFunctions::Replace(m_template,"[CONTENT]",content); } diff --git a/src/http/pages/peertrustpage.cpp b/src/http/pages/peertrustpage.cpp index dc689bf..ac6b053 100644 --- a/src/http/pages/peertrustpage.cpp +++ b/src/http/pages/peertrustpage.cpp @@ -239,8 +239,9 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s } content+="

    Peer Trust

    "; - content+="Message Trust is how much you trust the identity to post good messages. Trust List Trust is how much weight you want the trust list of that identity to have when calculating the total. The local trust levels are set by you, and the peer trust levels are calculated by a weighted average using other identities' trust lists. Trust is recalculated once an hour from received trust lists. You must have at least 1 identity created and have received the SSK keypair for it from Freenet before setting trust."; - + content+="Message Trust is how much you trust the identity to post good messages. Trust List Trust is how much weight you want the trust list of that identity to have when calculating the total. The local trust levels are set by you, and the peer trust levels are calculated by a weighted average using other identities' trust lists. Trust is recalculated once an hour from received trust lists. You must have at least 1 identity created and have received the SSK keypair for it from Freenet before setting trust.
    "; + content+="* - This identity is not publishing a trust list
    "; + // search drop down content+="
    "; content+="
    "; @@ -276,7 +277,6 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s content+="Message Count"; content+="\r\n"; -//TODO - modify this query // get count of identities we are showing sql="SELECT COUNT(*) FROM tblIdentity LEFT JOIN (SELECT IdentityID FROM tblIdentityTrust WHERE LocalIdentityID=?) AS 'tblIdentityTrust' ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID "; sql+="WHERE tblIdentity.Hidden='false'"; @@ -296,7 +296,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s st.ResultInt(0,identitycount); st.Finalize(); - sql="SELECT tblIdentity.IdentityID,Name,tblIdentityTrust.LocalMessageTrust,PeerMessageTrust,tblIdentityTrust.LocalTrustListTrust,PeerTrustListTrust,PublicKey,tblIdentityTrust.MessageTrustComment,tblIdentityTrust.TrustListTrustComment,COUNT(MessageID) AS 'MessageCount' "; + sql="SELECT tblIdentity.IdentityID,Name,tblIdentityTrust.LocalMessageTrust,PeerMessageTrust,tblIdentityTrust.LocalTrustListTrust,PeerTrustListTrust,PublicKey,tblIdentityTrust.MessageTrustComment,tblIdentityTrust.TrustListTrustComment,COUNT(MessageID) AS 'MessageCount',tblIdentity.PublishTrustList "; sql+="FROM tblIdentity LEFT JOIN (SELECT LocalIdentityID,IdentityID,LocalMessageTrust,LocalTrustListTrust,MessageTrustComment,TrustListTrustComment FROM tblIdentityTrust WHERE LocalIdentityID=?) AS tblIdentityTrust ON tblIdentity.IdentityID=tblIdentityTrust.IdentityID LEFT JOIN tblMessage ON tblIdentity.IdentityID=tblMessage.IdentityID "; sql+="WHERE tblIdentity.Hidden='false'"; if(namesearch!="") @@ -339,6 +339,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s std::string messagetrustcomment=""; std::string trustlisttrustcomment=""; std::string messagecountstr=""; + std::string publishtrustlist=""; StringFunctions::Convert(count,countstr); @@ -352,6 +353,7 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s st.ResultText(7,messagetrustcomment); st.ResultText(8,trustlisttrustcomment); st.ResultText(9,messagecountstr); + st.ResultText(10,publishtrustlist); content+=""; content+=""; @@ -378,7 +380,12 @@ const std::string PeerTrustPage::GeneratePage(const std::string &method, const s content+=peermessagetrust+""; content+=""; content+=""; - content+=""; + content+=""; + if(publishtrustlist=="false") + { + content+="*"; + } + content+=""; content+=""; content+=""; content+=""; diff --git a/src/message.cpp b/src/message.cpp index 53d8b34..f8b64e5 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -738,8 +738,6 @@ const bool Message::StartFreenetInsert() xml.SetSubject(m_subject); xml.SetBody(m_body); xml.SetReplyBoard(m_replyboardname); - xml.SetDate(m_datetime.Format("%Y-%m-%d")); - xml.SetTime(m_datetime.Format("%H:%M:%S")); for(std::vector::iterator i=m_boards.begin(); i!=m_boards.end(); i++) { @@ -757,10 +755,43 @@ const bool Message::StartFreenetInsert() return false; } - SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,MessageUUID,MessageXML) VALUES(?,?,?);"); + // add the message delay if there is one + SQLite3DB::Statement st=m_db->Prepare("SELECT MinMessageDelay,MaxMessageDelay FROM tblLocalIdentity WHERE LocalIdentityID=?;"); + st.Bind(0,localidentityid); + st.Step(); + if(st.RowReturned()) + { + int min=0; + int max=0; + st.ResultInt(0,min); + st.ResultInt(1,max); + + min<0 ? min=0 : false; + max<0 ? max=0 : false; + min>max ? min=max : false; + + if(min==max) + { + m_datetime.Add(0,min); + } + else if(max>min) + { + int delay=(rand()%(max-min))+min; + m_datetime.Add(0,delay); + } + + } + st.Finalize(); + + // set date in xml file AFTER we set the delay + xml.SetDate(m_datetime.Format("%Y-%m-%d")); + xml.SetTime(m_datetime.Format("%H:%M:%S")); + + st=m_db->Prepare("INSERT INTO tblMessageInserts(LocalIdentityID,MessageUUID,MessageXML,SendDate) VALUES(?,?,?,?);"); st.Bind(0,localidentityid); st.Bind(1,m_messageuuid); st.Bind(2,xml.GetXML()); + st.Bind(3,m_datetime.Format("%Y-%m-%d %H:%M:%S")); st.Step(); // insert file attachments into database -- 2.7.4